ソースを参照

Added an AppProperty for enabling/disabling macro replacement in regular expressions.

This involved updating the PwmPasswordRule so it was aware of AppProperties, since up to this point it only knew about ChaiPasswordRule and PwmSetting.
James Albright 9 年 前
コミット
6c2017a444

+ 1 - 0
src/main/java/password/pwm/AppProperty.java

@@ -231,6 +231,7 @@ public enum AppProperty {
     URL_SHORTNER_URL_REGEX                          ("urlshortener.url.regex"),
     WORDLIST_BUILTIN_PATH                           ("wordlist.builtin.path"),
     WS_REST_CLIENT_PWRULE_HALTONERROR               ("ws.restClient.pwRule.haltOnError"),
+    ALLOW_MACRO_IN_REGEX_SETTING                    ("password.policy.allowMacroInRegexSetting"),
 
     ;
 

+ 4 - 1
src/main/java/password/pwm/config/Configuration.java

@@ -377,7 +377,7 @@ public class Configuration implements Serializable, SettingReader {
     {
         final Map<String, String> passwordPolicySettings = new LinkedHashMap<>();
         for (final PwmPasswordRule rule : PwmPasswordRule.values()) {
-            if (rule.getPwmSetting() != null) {
+            if (rule.getPwmSetting() != null || rule.getAppProperty() != null) {
                 final String value;
                 final PwmSetting pwmSetting = rule.getPwmSetting();
                 switch (rule) {
@@ -403,6 +403,9 @@ public class Configuration implements Serializable, SettingReader {
                                 ADPolicyComplexity.class
                         ).toString();
                         break;
+                    case AllowMacroInRegExSetting:
+                        value = readAppProperty(AppProperty.ALLOW_MACRO_IN_REGEX_SETTING);
+                        break;
                     default:
                         value = String.valueOf(
                                 storedConfiguration.readSetting(pwmSetting, profile).toNativeObject());

+ 24 - 8
src/main/java/password/pwm/config/profile/PwmPasswordPolicy.java

@@ -35,6 +35,10 @@ import java.util.Set;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
 
+import org.apache.commons.lang.StringUtils;
+
+import password.pwm.PwmApplication;
+import password.pwm.config.PwmSetting;
 import password.pwm.config.UserPermission;
 import password.pwm.config.option.ADPolicyComplexity;
 import password.pwm.health.HealthMessage;
@@ -194,6 +198,7 @@ public class PwmPasswordPolicy implements Profile,Serializable {
         for (final PwmPasswordRule rule : PwmPasswordRule.values()) {
             final String ruleKey = rule.getKey();
             if (this.policyMap.containsKey(ruleKey) || otherPolicy.policyMap.containsKey(ruleKey)) {
+
                 switch (rule) {
                     case DisallowedValues:
                     case DisallowedAttributes:
@@ -217,26 +222,33 @@ public class PwmPasswordPolicy implements Profile,Serializable {
                         break;
 
                     case ExpirationInterval:
-                        newPasswordPolicies.put(ruleKey, mergeMin(policyMap.get(ruleKey), otherPolicy.policyMap.get(ruleKey)));
+                        final String expirationIntervalLocalValue = StringUtils.defaultString(policyMap.get(ruleKey), rule.getDefaultValue());
+                        final String expirationIntervalOtherValue = StringUtils.defaultString(otherPolicy.policyMap.get(ruleKey), rule.getDefaultValue());
+                        newPasswordPolicies.put(ruleKey, mergeMin(expirationIntervalLocalValue, expirationIntervalOtherValue));
                         break;
 
                     case MinimumLifetime:
-                        newPasswordPolicies.put(ruleKey, mergeMin(policyMap.get(ruleKey), otherPolicy.policyMap.get(ruleKey)));
+                        final String minimumLifetimeLocalValue = StringUtils.defaultString(policyMap.get(ruleKey), rule.getDefaultValue());
+                        final String minimumLifetimeOtherValue = StringUtils.defaultString(otherPolicy.policyMap.get(ruleKey), rule.getDefaultValue());
+                        newPasswordPolicies.put(ruleKey, mergeMin(minimumLifetimeLocalValue, minimumLifetimeOtherValue));
                         break;
 
                     default:
+                        final String localValueString = StringUtils.defaultString(policyMap.get(ruleKey), rule.getDefaultValue());
+                        final String otherValueString = StringUtils.defaultString(otherPolicy.policyMap.get(ruleKey), rule.getDefaultValue());
+
                         switch (rule.getRuleType()) {
                             case MIN:
-                                newPasswordPolicies.put(ruleKey, mergeMin(policyMap.get(ruleKey), otherPolicy.policyMap.get(ruleKey)));
+                                newPasswordPolicies.put(ruleKey, mergeMin(localValueString, otherValueString));
                                 break;
 
                             case MAX:
-                                newPasswordPolicies.put(ruleKey, mergeMax(policyMap.get(ruleKey), otherPolicy.policyMap.get(ruleKey)));
+                                newPasswordPolicies.put(ruleKey, mergeMax(localValueString, otherValueString));
                                 break;
 
                             case BOOLEAN:
-                                final boolean localValue = StringHelper.convertStrToBoolean(policyMap.get(ruleKey));
-                                final boolean otherValue = StringHelper.convertStrToBoolean(otherPolicy.policyMap.get(ruleKey));
+                                final boolean localValue = StringHelper.convertStrToBoolean(localValueString);
+                                final boolean otherValue = StringHelper.convertStrToBoolean(otherValueString);
 
                                 if (rule.isPositiveBooleanMerge()) {
                                     newPasswordPolicies.put(ruleKey, String.valueOf(localValue || otherValue));
@@ -372,7 +384,7 @@ public class PwmPasswordPolicy implements Profile,Serializable {
             return readRegExSetting(rule, macroMachine, input);
         }
 
-        static List<Pattern> readRegExSetting(final PwmPasswordRule rule, final MacroMachine macroMachine, final String input) {
+        List<Pattern> readRegExSetting(final PwmPasswordRule rule, final MacroMachine macroMachine, final String input) {
             if (input == null) {
                 return Collections.emptyList();
             }
@@ -383,7 +395,11 @@ public class PwmPasswordPolicy implements Profile,Serializable {
 
             for (final String value : values) {
                 if (value != null && value.length() > 0) {
-                    final String valueToCompile = (macroMachine == null) ? value : macroMachine.expandMacros(value);
+                    String valueToCompile = value;
+
+                    if (macroMachine != null && readBooleanValue(PwmPasswordRule.AllowMacroInRegExSetting)) {
+                        valueToCompile = macroMachine.expandMacros(value);
+                    }
 
                     try {
                         final Pattern loopPattern = Pattern.compile(valueToCompile);

+ 28 - 6
src/main/java/password/pwm/config/profile/PwmPasswordRule.java

@@ -22,17 +22,19 @@
 
 package password.pwm.config.profile;
 
-import com.novell.ldapchai.ChaiPasswordRule;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.Set;
+
+import password.pwm.AppProperty;
 import password.pwm.config.Configuration;
 import password.pwm.config.PwmSetting;
 import password.pwm.i18n.Message;
 import password.pwm.util.LocaleHelper;
 import password.pwm.util.logging.PwmLogger;
 
-import java.util.HashSet;
-import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.Set;
+import com.novell.ldapchai.ChaiPasswordRule;
 
 /**
  * Password rules
@@ -93,6 +95,7 @@ public enum PwmPasswordRule {
     CharGroupsMinMatch          (null                                      ,PwmSetting.PASSWORD_POLICY_CHAR_GROUPS_MIN_MATCH        ,ChaiPasswordRule.RuleType.MIN, "0",false),
     CharGroupsValues            (null                                      ,PwmSetting.PASSWORD_POLICY_CHAR_GROUPS                  ,ChaiPasswordRule.RuleType.OTHER, "",false),
 
+    AllowMacroInRegExSetting    (                                           AppProperty.ALLOW_MACRO_IN_REGEX_SETTING                ,ChaiPasswordRule.RuleType.BOOLEAN, "true", false), 
     ;
 
     private static final PwmLogger LOGGER = PwmLogger.forClass(PwmPasswordRule.class);
@@ -109,6 +112,7 @@ public enum PwmPasswordRule {
 
     private final ChaiPasswordRule chaiPasswordRule;
     private final PwmSetting pwmSetting;
+    private final AppProperty appProperty;
     private final ChaiPasswordRule.RuleType ruleType;
     private final String defaultValue;
     private final boolean positiveBooleanMerge;
@@ -116,19 +120,37 @@ public enum PwmPasswordRule {
     PwmPasswordRule(final ChaiPasswordRule chaiPasswordRule, final PwmSetting pwmSetting, final ChaiPasswordRule.RuleType ruleType, final String defaultValue, final boolean positiveBooleanMerge) {
         this.pwmSetting = pwmSetting;
         this.chaiPasswordRule = chaiPasswordRule;
+        this.appProperty = null;
+        this.ruleType = ruleType;
+        this.defaultValue = defaultValue;
+        this.positiveBooleanMerge = positiveBooleanMerge;
+    }
+
+    PwmPasswordRule(final AppProperty appProperty, final ChaiPasswordRule.RuleType ruleType, final String defaultValue, final boolean positiveBooleanMerge) {
+        this.pwmSetting = null;
+        this.chaiPasswordRule = null;
+        this.appProperty = appProperty;
         this.ruleType = ruleType;
         this.defaultValue = defaultValue;
         this.positiveBooleanMerge = positiveBooleanMerge;
     }
 
     public String getKey() {
-        return null != chaiPasswordRule ? chaiPasswordRule.getKey() : pwmSetting.getKey();
+        if (chaiPasswordRule != null) return chaiPasswordRule.getKey();
+        if (pwmSetting       != null) return pwmSetting.getKey();
+        if (appProperty      != null) return appProperty.getKey();
+
+        return this.name();
     }
 
     public PwmSetting getPwmSetting() {
         return pwmSetting;
     }
 
+    public AppProperty getAppProperty() {
+        return appProperty;
+    }
+
     public ChaiPasswordRule.RuleType getRuleType() {
         return ruleType;
     }

+ 1 - 0
src/main/resources/password/pwm/AppProperty.properties

@@ -212,3 +212,4 @@ token.maxUniqueCreateAttempts=100
 urlshortener.url.regex=(https?://([^:@]+(:[^@]+)?@)?([a-zA-Z0-9.]+|d{1,3}.d{1,3}.d{1,3}.d{1,3}|[[0-9a-fA-F:]+])(:d{1,5})?/*[a-zA-Z0-9/\%_.]*?*[a-zA-Z0-9/\%_.=&#]*)
 wordlist.builtin.path=/WEB-INF/wordlist.zip
 ws.restClient.pwRule.haltOnError=true
+password.policy.allowMacroInRegexSetting=true

+ 14 - 6
src/test/java/password/pwm/config/profile/RuleHelperTest.java

@@ -9,6 +9,7 @@ import java.util.List;
 import java.util.regex.Pattern;
 
 import org.apache.commons.lang.StringUtils;
+import org.junit.Before;
 import org.junit.Test;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
@@ -25,13 +26,21 @@ public class RuleHelperTest {
     };
 
     private MacroMachine macroMachine = mock(MacroMachine.class);
+    private RuleHelper ruleHelper = mock(RuleHelper.class);
 
-    @Test
-    public void testReadRegExSetting_noRegex() throws Exception {
+    @Before
+    public void setUp() throws Exception {
+        // Mock out things that don't need to be real
         when(macroMachine.expandMacros(anyString())).thenAnswer(replaceAllMacrosInMap(MACRO_MAP));
+        when(ruleHelper.readBooleanValue(PwmPasswordRule.AllowMacroInRegExSetting)).thenReturn(Boolean.TRUE);
+        when(ruleHelper.readRegExSetting(any(PwmPasswordRule.class), any(MacroMachine.class), anyString())).thenCallRealMethod();
+    }
 
+    @Test
+    public void testReadRegExSetting_noRegex() throws Exception {
         final String input = "@User:ID@, First Name: @LDAP:givenName@, Last Name: @LDAP:sn@, Email: @User:Email@";
-        final List<Pattern> patterns = RuleHelper.readRegExSetting(RegExMatch, macroMachine, input);
+
+        final List<Pattern> patterns = ruleHelper.readRegExSetting(RegExMatch, macroMachine, input);
 
         assertThat(patterns.size()).isEqualTo(1);
         assertThat(patterns.get(0).pattern()).isEqualTo("fflintstone, First Name: Fred, Last Name: Flintstone, Email: fred@flintstones.tv");
@@ -39,10 +48,9 @@ public class RuleHelperTest {
 
     @Test
     public void testReadRegExSetting() throws Exception {
-        when(macroMachine.expandMacros(anyString())).thenAnswer(replaceAllMacrosInMap(MACRO_MAP));
-
         final String input = "^@User:ID@[0-9]+$;;;^password$";
-        final List<Pattern> patterns = RuleHelper.readRegExSetting(RegExMatch, macroMachine, input);
+
+        final List<Pattern> patterns = ruleHelper.readRegExSetting(RegExMatch, macroMachine, input);
 
         assertThat(patterns.size()).isEqualTo(2);
         assertThat(patterns.get(0).pattern()).isEqualTo("^fflintstone[0-9]+$");