This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch WW-5077-dmi-aware
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 1b0c743e85aefd81485185f31441c6f7f6898cba
Author: Lukasz Lenart <lukaszlen...@apache.org>
AuthorDate: Sat Jul 11 20:31:30 2020 +0200

    WW-5077 Uses a different pattern if DMI is enabled
---
 .../security/DefaultAcceptedPatternsChecker.java   |  23 +++-
 .../security/DefaultExcludedPatternsChecker.java   |   2 +-
 .../DefaultAcceptedPatternsCheckerTest.java        | 136 +++++++++++++--------
 3 files changed, 104 insertions(+), 57 deletions(-)

diff --git 
a/core/src/main/java/com/opensymphony/xwork2/security/DefaultAcceptedPatternsChecker.java
 
b/core/src/main/java/com/opensymphony/xwork2/security/DefaultAcceptedPatternsChecker.java
index 38f2b7e..2745955 100644
--- 
a/core/src/main/java/com/opensymphony/xwork2/security/DefaultAcceptedPatternsChecker.java
+++ 
b/core/src/main/java/com/opensymphony/xwork2/security/DefaultAcceptedPatternsChecker.java
@@ -21,8 +21,10 @@ package com.opensymphony.xwork2.security;
 import com.opensymphony.xwork2.XWorkConstants;
 import com.opensymphony.xwork2.inject.Inject;
 import com.opensymphony.xwork2.util.TextParseUtil;
+import org.apache.commons.lang3.BooleanUtils;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
+import org.apache.struts2.StrutsConstants;
 
 import java.util.Arrays;
 import java.util.Collections;
@@ -35,7 +37,11 @@ public class DefaultAcceptedPatternsChecker implements 
AcceptedPatternsChecker {
     private static final Logger LOG = 
LogManager.getLogger(DefaultAcceptedPatternsChecker.class);
 
     public static final String[] ACCEPTED_PATTERNS = {
-            
"\\w+((\\.\\w+)|(\\[\\d+\\])|(\\(\\d+\\))|(\\['(\\w|[\\u4e00-\\u9fa5])+'\\])|(\\('(\\w|[\\u4e00-\\u9fa5])+'\\)))*"
+            
"\\w+((\\.\\w+)|(\\[\\d+])|(\\(\\d+\\))|(\\['(\\w|[\\u4e00-\\u9fa5])+'])|(\\('(\\w|[\\u4e00-\\u9fa5])+'\\)))*"
+    };
+
+    public static final String[] DMI_AWARE_ACCEPTED_PATTERNS = {
+            
"\\w+([:]?\\w+)*((\\.\\w+)|(\\[\\d+])|(\\(\\d+\\))|(\\['(\\w|[\\u4e00-\\u9fa5])+'])|(\\('(\\w|[\\u4e00-\\u9fa5])+'\\)))*([!]?\\w+)*"
     };
 
     private Set<Pattern> acceptedPatterns;
@@ -44,10 +50,21 @@ public class DefaultAcceptedPatternsChecker implements 
AcceptedPatternsChecker {
         setAcceptedPatterns(ACCEPTED_PATTERNS);
     }
 
+    public DefaultAcceptedPatternsChecker(
+            @Inject(value = 
StrutsConstants.STRUTS_ENABLE_DYNAMIC_METHOD_INVOCATION, required = false) 
String dmiValue
+    ) {
+        if (BooleanUtils.toBoolean(dmiValue)) {
+            LOG.debug("DMI is enabled, adding DMI related accepted patterns");
+            setAcceptedPatterns(DMI_AWARE_ACCEPTED_PATTERNS);
+        } else {
+            setAcceptedPatterns(ACCEPTED_PATTERNS);
+        }
+    }
+
     @Inject(value = XWorkConstants.OVERRIDE_ACCEPTED_PATTERNS, required = 
false)
     protected void setOverrideAcceptedPatterns(String acceptablePatterns) {
         LOG.warn("Overriding accepted patterns [{}] with [{}], be aware that 
this affects all instances and safety of your application!",
-                    acceptedPatterns, acceptablePatterns);
+                acceptedPatterns, acceptablePatterns);
         acceptedPatterns = new HashSet<>();
         try {
             for (String pattern : 
TextParseUtil.commaDelimitedStringToSet(acceptablePatterns)) {
@@ -88,7 +105,7 @@ public class DefaultAcceptedPatternsChecker implements 
AcceptedPatternsChecker {
             LOG.debug("Sets accepted patterns to [{}], note this impacts the 
safety of your application!", patterns);
         } else {
             LOG.warn("Replacing accepted patterns [{}] with [{}], be aware 
that this affects all instances and safety of your application!",
-                        acceptedPatterns, patterns);
+                    acceptedPatterns, patterns);
         }
         acceptedPatterns = new HashSet<>(patterns.size());
         try {
diff --git 
a/core/src/main/java/com/opensymphony/xwork2/security/DefaultExcludedPatternsChecker.java
 
b/core/src/main/java/com/opensymphony/xwork2/security/DefaultExcludedPatternsChecker.java
index 761e794..e1c2aa9 100644
--- 
a/core/src/main/java/com/opensymphony/xwork2/security/DefaultExcludedPatternsChecker.java
+++ 
b/core/src/main/java/com/opensymphony/xwork2/security/DefaultExcludedPatternsChecker.java
@@ -81,7 +81,7 @@ public class DefaultExcludedPatternsChecker implements 
ExcludedPatternsChecker {
 
     @Inject(StrutsConstants.STRUTS_ENABLE_DYNAMIC_METHOD_INVOCATION)
     protected void setDynamicMethodInvocation(String dmiValue) {
-        if (BooleanUtils.toBoolean(dmiValue) == false) {
+        if (!BooleanUtils.toBoolean(dmiValue)) {
             LOG.debug("DMI is disabled, adding DMI related excluded patterns");
             setAdditionalExcludePatterns("^(action|method):.*");
         }
diff --git 
a/core/src/test/java/com/opensymphony/xwork2/security/DefaultAcceptedPatternsCheckerTest.java
 
b/core/src/test/java/com/opensymphony/xwork2/security/DefaultAcceptedPatternsCheckerTest.java
index 5e5356a..1dc8d8a 100644
--- 
a/core/src/test/java/com/opensymphony/xwork2/security/DefaultAcceptedPatternsCheckerTest.java
+++ 
b/core/src/test/java/com/opensymphony/xwork2/security/DefaultAcceptedPatternsCheckerTest.java
@@ -27,41 +27,41 @@ import java.util.regex.Pattern;
 
 public class DefaultAcceptedPatternsCheckerTest extends XWorkTestCase {
 
-    public void testHardcodedAcceptedPatterns() throws Exception {
-        // given
-        List<String> params = new ArrayList<String>() {
-            {
-                add("%{#application['test']}");
-                add("%{#application.test}");
-                add("%{#Application['test']}");
-                add("%{#Application.test}");
-                add("%{#session['test']}");
-                add("%{#session.test}");
-                add("%{#Session['test']}");
-                add("%{#Session.test}");
-                add("%{#struts['test']}");
-                add("%{#struts.test}");
-                add("%{#Struts['test']}");
-                add("%{#Struts.test}");
-                add("%{#request['test']}");
-                add("%{#request.test}");
-                add("%{#Request['test']}");
-                add("%{#Request.test}");
-                add("%{#servletRequest['test']}");
-                add("%{#servletRequest.test}");
-                add("%{#ServletRequest['test']}");
-                add("%{#ServletRequest.test}");
-                add("%{#servletResponse['test']}");
-                add("%{#servletResponse.test}");
-                add("%{#ServletResponse['test']}");
-                add("%{#ServletResponse.test}");
-                add("%{#parameters['test']}");
-                add("%{#parameters.test}");
-                add("%{#Parameters['test']}");
-                add("%{#Parameters.test}");
-            }
-        };
+    private final List<String> params = new ArrayList<String>() {
+        {
+            add("%{#application['test']}");
+            add("%{#application.test}");
+            add("%{#Application['test']}");
+            add("%{#Application.test}");
+            add("%{#session['test']}");
+            add("%{#session.test}");
+            add("%{#Session['test']}");
+            add("%{#Session.test}");
+            add("%{#struts['test']}");
+            add("%{#struts.test}");
+            add("%{#Struts['test']}");
+            add("%{#Struts.test}");
+            add("%{#request['test']}");
+            add("%{#request.test}");
+            add("%{#Request['test']}");
+            add("%{#Request.test}");
+            add("%{#servletRequest['test']}");
+            add("%{#servletRequest.test}");
+            add("%{#ServletRequest['test']}");
+            add("%{#ServletRequest.test}");
+            add("%{#servletResponse['test']}");
+            add("%{#servletResponse.test}");
+            add("%{#ServletResponse['test']}");
+            add("%{#ServletResponse.test}");
+            add("%{#parameters['test']}");
+            add("%{#parameters.test}");
+            add("%{#Parameters['test']}");
+            add("%{#Parameters.test}");
+        }
+    };
 
+    public void testHardcodedAcceptedPatterns() {
+        // given
         AcceptedPatternsChecker checker = new DefaultAcceptedPatternsChecker();
 
         for (String param : params) {
@@ -73,7 +73,20 @@ public class DefaultAcceptedPatternsCheckerTest extends 
XWorkTestCase {
         }
     }
 
-    public void testUnderscoreInParamName() throws Exception {
+    public void testHardcodedAcceptedPatternsWithDmiEnabled() {
+        // given
+        AcceptedPatternsChecker checker = new 
DefaultAcceptedPatternsChecker(Boolean.TRUE.toString());
+
+        for (String param : params) {
+            // when
+            AcceptedPatternsChecker.IsAccepted actual = 
checker.isAccepted(param);
+
+            // then
+            assertFalse("Access to " + param + " is possible!", 
actual.isAccepted());
+        }
+    }
+
+    public void testUnderscoreInParamName() {
         // given
         AcceptedPatternsChecker checker = new DefaultAcceptedPatternsChecker();
 
@@ -84,22 +97,33 @@ public class DefaultAcceptedPatternsCheckerTest extends 
XWorkTestCase {
         assertTrue("Param with underscore wasn't accepted!", 
actual.isAccepted());
     }
 
-    public void testAcceptedPatternsImmutable() throws Exception {
+    public void testUnderscoreInParamNameWithDmiEnabled() {
+        // given
+        AcceptedPatternsChecker checker = new 
DefaultAcceptedPatternsChecker(Boolean.TRUE.toString());
+
+        // when
+        AcceptedPatternsChecker.IsAccepted actual = 
checker.isAccepted("mapParam['param_1']");
+
+        // then
+        assertTrue("Param with underscore wasn't accepted!", 
actual.isAccepted());
+    }
+
+    public void testAcceptedPatternsImmutable() {
         AcceptedPatternsChecker checker = new DefaultAcceptedPatternsChecker();
 
         Set<Pattern> acceptedPatternSet = checker.getAcceptedPatterns();
         assertNotNull("default accepted patterns null?", acceptedPatternSet);
         assertFalse("default accepted patterns empty?", 
acceptedPatternSet.isEmpty());
         try {
-            acceptedPatternSet.add(Pattern.compile("SomeRegexPattern") );
-            fail ("accepted patterns modifiable?");
-        } catch(UnsupportedOperationException uoe) {
+            acceptedPatternSet.add(Pattern.compile("SomeRegexPattern"));
+            fail("accepted patterns modifiable?");
+        } catch (UnsupportedOperationException uoe) {
             // Expected result
         }
         try {
             acceptedPatternSet.clear();
-            fail ("accepted patterns modifiable?");
-        } catch(UnsupportedOperationException uoe) {
+            fail("accepted patterns modifiable?");
+        } catch (UnsupportedOperationException uoe) {
             // Expected result
         }
 
@@ -108,15 +132,15 @@ public class DefaultAcceptedPatternsCheckerTest extends 
XWorkTestCase {
         assertNotNull("replaced default accepted patterns null?", 
acceptedPatternSet);
         assertFalse("replaced default accepted patterns empty?", 
acceptedPatternSet.isEmpty());
         try {
-            acceptedPatternSet.add(Pattern.compile("SomeRegexPattern") );
-            fail ("replaced accepted patterns modifiable?");
-        } catch(UnsupportedOperationException uoe) {
+            acceptedPatternSet.add(Pattern.compile("SomeRegexPattern"));
+            fail("replaced accepted patterns modifiable?");
+        } catch (UnsupportedOperationException uoe) {
             // Expected result
         }
         try {
             acceptedPatternSet.clear();
-            fail ("accepted patterns modifiable?");
-        } catch(UnsupportedOperationException uoe) {
+            fail("accepted patterns modifiable?");
+        } catch (UnsupportedOperationException uoe) {
             // Expected result
         }
 
@@ -125,23 +149,29 @@ public class DefaultAcceptedPatternsCheckerTest extends 
XWorkTestCase {
         acceptedPatternSet = checker.getAcceptedPatterns();
         assertNotNull("replaced default accepted patterns null?", 
acceptedPatternSet);
         assertFalse("replaced default accepted patterns empty?", 
acceptedPatternSet.isEmpty());
-        assertTrue("replaced default accepted patterns not size " + 
testPatternArray.length + "?",
-                acceptedPatternSet.size() == testPatternArray.length);
+        assertEquals("replaced default accepted patterns not size " + 
testPatternArray.length + "?", acceptedPatternSet.size(), 
testPatternArray.length);
         for (String testPatternArray1 : testPatternArray) {
             assertTrue(testPatternArray1 + " not accepted?", 
checker.isAccepted(testPatternArray1).isAccepted());
         }
         try {
-            acceptedPatternSet.add(Pattern.compile("SomeRegexPattern") );
-            fail ("replaced accepted patterns modifiable?");
-        } catch(UnsupportedOperationException uoe) {
+            acceptedPatternSet.add(Pattern.compile("SomeRegexPattern"));
+            fail("replaced accepted patterns modifiable?");
+        } catch (UnsupportedOperationException uoe) {
             // Expected result
         }
         try {
             acceptedPatternSet.clear();
-            fail ("accepted patterns modifiable?");
-        } catch(UnsupportedOperationException uoe) {
+            fail("accepted patterns modifiable?");
+        } catch (UnsupportedOperationException uoe) {
             // Expected result
         }
+    }
+
+    public void testDmiIsEnabled() {
+        DefaultAcceptedPatternsChecker checker = new 
DefaultAcceptedPatternsChecker(Boolean.TRUE.toString());
+
+        AcceptedPatternsChecker.IsAccepted accepted = 
checker.isAccepted("action:myAction!save");
 
+        assertTrue("dmi isn't accepted", accepted.isAccepted());
     }
 }
\ No newline at end of file

Reply via email to