Author: lukaszlenart
Date: Fri Oct 18 06:47:31 2013
New Revision: 1533336

URL: http://svn.apache.org/r1533336
Log:
WW-4227 Adds first step to define internal security mechanism

Added:
    struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/
    
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/DefaultSecurityGate.java
    
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/ParameterNameSecurityGuard.java
    
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/ParameterValueSecurityGuard.java
    
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityGate.java
    
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityGuard.java
    
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityPass.java
    
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/StrutsSecurityException.java
    struts/struts2/trunk/core/src/test/java/org/apache/struts2/security/
    
struts/struts2/trunk/core/src/test/java/org/apache/struts2/security/ParameterNameSecurityGuardTest.java
    
struts/struts2/trunk/core/src/test/java/org/apache/struts2/security/ParameterValueSecurityGuardTest.java
Modified:
    
struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java
    
struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/BeanSelectionProvider.java
    
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java
    
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/PrepareOperations.java
    struts/struts2/trunk/core/src/main/resources/struts-default.xml

Modified: 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java?rev=1533336&r1=1533335&r2=1533336&view=diff
==============================================================================
--- 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java 
(original)
+++ 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java 
Fri Oct 18 06:47:31 2013
@@ -268,4 +268,7 @@ public final class StrutsConstants {
     /** actions names' whitelist **/
     public static final String STRUTS_ALLOWED_ACTION_NAMES = 
"struts.allowed.action.names";
 
+    /** Security firewall **/
+    public static final String STRUTS_SECURITY_GATE = "struts.securityGate";
+
 }

Modified: 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/BeanSelectionProvider.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/BeanSelectionProvider.java?rev=1533336&r1=1533335&r2=1533336&view=diff
==============================================================================
--- 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/BeanSelectionProvider.java
 (original)
+++ 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/BeanSelectionProvider.java
 Fri Oct 18 06:47:31 2013
@@ -70,6 +70,7 @@ import org.apache.struts2.components.Url
 import org.apache.struts2.dispatcher.StaticContentLoader;
 import org.apache.struts2.dispatcher.mapper.ActionMapper;
 import org.apache.struts2.dispatcher.multipart.MultiPartRequest;
+import org.apache.struts2.security.SecurityGate;
 import org.apache.struts2.views.freemarker.FreemarkerManager;
 import org.apache.struts2.views.util.UrlHelper;
 import org.apache.struts2.views.velocity.VelocityManager;
@@ -406,6 +407,8 @@ public class BeanSelectionProvider imple
 
         alias(TextParser.class, StrutsConstants.STRUTS_EXPRESSION_PARSER, 
builder, props);
 
+        alias(SecurityGate.class, StrutsConstants.STRUTS_SECURITY_GATE, 
builder, props);
+
         if 
("true".equalsIgnoreCase(props.getProperty(StrutsConstants.STRUTS_DEVMODE))) {
             props.setProperty(StrutsConstants.STRUTS_I18N_RELOAD, "true");
             props.setProperty(StrutsConstants.STRUTS_CONFIGURATION_XML_RELOAD, 
"true");

Modified: 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java?rev=1533336&r1=1533335&r2=1533336&view=diff
==============================================================================
--- 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java
 (original)
+++ 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java
 Fri Oct 18 06:47:31 2013
@@ -65,6 +65,7 @@ import org.apache.struts2.config.StrutsX
 import org.apache.struts2.dispatcher.mapper.ActionMapping;
 import org.apache.struts2.dispatcher.multipart.MultiPartRequest;
 import org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper;
+import org.apache.struts2.security.SecurityGate;
 import org.apache.struts2.util.AttributeMap;
 import org.apache.struts2.util.ObjectFactoryDestroyable;
 import org.apache.struts2.util.fs.JBossFileManager;
@@ -209,6 +210,7 @@ public class Dispatcher {
 
     private ValueStackFactory valueStackFactory;
 
+    private SecurityGate securityGate;
 
     /**
      * Create the Dispatcher instance for a given ServletContext and set of 
initialization parameters.
@@ -281,6 +283,11 @@ public class Dispatcher {
         this.handleException = Boolean.parseBoolean(handleException);
     }
 
+    @Inject
+    public void setSecurityGate(SecurityGate securityGate) {
+        this.securityGate = securityGate;
+    }
+
     /**
      * Releases all instances bound to this dispatcher instance.
      */
@@ -930,6 +937,15 @@ public class Dispatcher {
     }
 
     /**
+     * Checks if request doesn't contain suspicious values
+     *
+     * @param request current {@link HttpServletRequest}
+     */
+    public void checkRequest(HttpServletRequest request) {
+        securityGate.check(request);
+    }
+
+    /**
      * Provide an accessor class for static XWork utility.
      */
     public static class Locator {

Modified: 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/PrepareOperations.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/PrepareOperations.java?rev=1533336&r1=1533335&r2=1533336&view=diff
==============================================================================
--- 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/PrepareOperations.java
 (original)
+++ 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/PrepareOperations.java
 Fri Oct 18 06:47:31 2013
@@ -158,6 +158,7 @@ public class PrepareOperations {
         ActionMapping mapping = (ActionMapping) 
request.getAttribute(STRUTS_ACTION_MAPPING_KEY);
         if (mapping == null || forceLookup) {
             try {
+                dispatcher.checkRequest(request);
                 mapping = 
dispatcher.getContainer().getInstance(ActionMapper.class).getMapping(request, 
dispatcher.getConfigurationManager());
                 if (mapping != null) {
                     request.setAttribute(STRUTS_ACTION_MAPPING_KEY, mapping);

Added: 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/DefaultSecurityGate.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/DefaultSecurityGate.java?rev=1533336&view=auto
==============================================================================
--- 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/DefaultSecurityGate.java
 (added)
+++ 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/DefaultSecurityGate.java
 Fri Oct 18 06:47:31 2013
@@ -0,0 +1,56 @@
+package org.apache.struts2.security;
+
+import com.opensymphony.xwork2.inject.Container;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
+import org.apache.struts2.StrutsConstants;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Default implementation of {@link org.apache.struts2.security.SecurityGate}
+ * just examines all the defined {@link 
org.apache.struts2.security.SecurityGuard}'s
+ */
+public class DefaultSecurityGate implements SecurityGate {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(DefaultSecurityGate.class);
+
+    private List<SecurityGuard> guards;
+    private boolean devMode;
+
+    @Inject(StrutsConstants.STRUTS_DEVMODE)
+    public void setDevMode(String devMode) {
+        this.devMode = "true".equalsIgnoreCase(devMode);
+    }
+
+    @Inject
+    public void setContainer(Container container) {
+        guards = new ArrayList<SecurityGuard>();
+        Set<String> guardNames = 
container.getInstanceNames(SecurityGate.class);
+        for (String guardName : guardNames) {
+            SecurityGuard guard = container.getInstance(SecurityGuard.class, 
guardName);
+            if (guard != null) {
+                guards.add(guard);
+            } else if (devMode) {
+                LOG.debug("Got null instance of [#0] for name [#1]", 
SecurityGuard.class.getSimpleName(), guardName);
+            }
+        }
+    }
+
+    public void check(HttpServletRequest request) {
+        for (SecurityGuard guard : guards) {
+            SecurityPass pass = guard.accept(request);
+            if (pass.isNotAccepted()) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("[#0] didn't accept the request!", 
guard.getClass().getName());
+                }
+                throw new StrutsSecurityException(pass.getGuardMessage());
+            }
+        }
+    }
+
+}

Added: 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/ParameterNameSecurityGuard.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/ParameterNameSecurityGuard.java?rev=1533336&view=auto
==============================================================================
--- 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/ParameterNameSecurityGuard.java
 (added)
+++ 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/ParameterNameSecurityGuard.java
 Fri Oct 18 06:47:31 2013
@@ -0,0 +1,14 @@
+package org.apache.struts2.security;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Checks if parameter name is valida and it doesn't contain vulnerable code
+ */
+public class ParameterNameSecurityGuard implements SecurityGuard {
+
+    public SecurityPass accept(HttpServletRequest request) {
+        return SecurityPass.accepted();
+    }
+
+}

Added: 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/ParameterValueSecurityGuard.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/ParameterValueSecurityGuard.java?rev=1533336&view=auto
==============================================================================
--- 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/ParameterValueSecurityGuard.java
 (added)
+++ 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/ParameterValueSecurityGuard.java
 Fri Oct 18 06:47:31 2013
@@ -0,0 +1,14 @@
+package org.apache.struts2.security;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Checks if parameter's value doesn't contain vulnerable code
+ */
+public class ParameterValueSecurityGuard implements SecurityGuard {
+
+    public SecurityPass accept(HttpServletRequest request) {
+        return SecurityPass.accepted();
+    }
+
+}

Added: 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityGate.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityGate.java?rev=1533336&view=auto
==============================================================================
--- 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityGate.java
 (added)
+++ 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityGate.java
 Fri Oct 18 06:47:31 2013
@@ -0,0 +1,12 @@
+package org.apache.struts2.security;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Main
+ */
+public interface SecurityGate {
+
+    void check(HttpServletRequest request);
+
+}

Added: 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityGuard.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityGuard.java?rev=1533336&view=auto
==============================================================================
--- 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityGuard.java
 (added)
+++ 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityGuard.java
 Fri Oct 18 06:47:31 2013
@@ -0,0 +1,12 @@
+package org.apache.struts2.security;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * TODO lukaszlenart: write a JavaDoc
+ */
+public interface SecurityGuard {
+
+    SecurityPass accept(HttpServletRequest request);
+
+}

Added: 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityPass.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityPass.java?rev=1533336&view=auto
==============================================================================
--- 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityPass.java
 (added)
+++ 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityPass.java
 Fri Oct 18 06:47:31 2013
@@ -0,0 +1,36 @@
+package org.apache.struts2.security;
+
+/**
+ * TODO lukaszlenart: write a JavaDoc
+ */
+public class SecurityPass {
+
+    private Boolean accepted;
+    private final String message;
+
+    public static SecurityPass accepted() {
+        return new SecurityPass(true, null);
+    }
+
+    public static SecurityPass notAccepted(String message) {
+        return new SecurityPass(false, message);
+    }
+
+    private SecurityPass(boolean accepted, String message) {
+        this.accepted = accepted;
+        this.message = message;
+    }
+
+    public String getGuardMessage() {
+        return message;
+    }
+
+    public boolean isAccepted() {
+        return accepted;
+    }
+
+    public boolean isNotAccepted() {
+        return !accepted;
+    }
+
+}

Added: 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/StrutsSecurityException.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/StrutsSecurityException.java?rev=1533336&view=auto
==============================================================================
--- 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/StrutsSecurityException.java
 (added)
+++ 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/StrutsSecurityException.java
 Fri Oct 18 06:47:31 2013
@@ -0,0 +1,14 @@
+package org.apache.struts2.security;
+
+import org.apache.struts2.StrutsException;
+
+/**
+ * Exception indicates possible security breach
+ */
+public class StrutsSecurityException extends StrutsException {
+
+    public StrutsSecurityException(String message) {
+        super(message);
+    }
+
+}

Modified: struts/struts2/trunk/core/src/main/resources/struts-default.xml
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/struts-default.xml?rev=1533336&r1=1533335&r2=1533336&view=diff
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/struts-default.xml (original)
+++ struts/struts2/trunk/core/src/main/resources/struts-default.xml Fri Oct 18 
06:47:31 2013
@@ -134,6 +134,10 @@
     <bean type="ognl.PropertyAccessor" name="java.util.HashSet" 
class="com.opensymphony.xwork2.ognl.accessor.XWorkCollectionPropertyAccessor" />
     <bean type="ognl.PropertyAccessor" name="java.util.HashMap" 
class="com.opensymphony.xwork2.ognl.accessor.XWorkMapPropertyAccessor" />
 
+    <bean type="org.apache.struts2.security.SecurityGate" name="struts" 
class="org.apache.struts2.security.DefaultSecurityGate" scope="singleton"/>
+    <bean type="org.apache.struts2.security.SecurityGuard" 
name="parameterNameGuard" 
class="org.apache.struts2.security.ParameterNameSecurityGuard" 
scope="singleton"/>
+    <bean type="org.apache.struts2.security.SecurityGuard" 
name="parameterValueGuard" 
class="org.apache.struts2.security.ParameterValueSecurityGuard" 
scope="singleton"/>
+
     <package name="struts-default" abstract="true">
         <result-types>
             <result-type name="chain" 
class="com.opensymphony.xwork2.ActionChainResult"/>

Added: 
struts/struts2/trunk/core/src/test/java/org/apache/struts2/security/ParameterNameSecurityGuardTest.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/java/org/apache/struts2/security/ParameterNameSecurityGuardTest.java?rev=1533336&view=auto
==============================================================================
--- 
struts/struts2/trunk/core/src/test/java/org/apache/struts2/security/ParameterNameSecurityGuardTest.java
 (added)
+++ 
struts/struts2/trunk/core/src/test/java/org/apache/struts2/security/ParameterNameSecurityGuardTest.java
 Fri Oct 18 06:47:31 2013
@@ -0,0 +1,28 @@
+package org.apache.struts2.security;
+
+import com.mockobjects.servlet.MockHttpServletRequest;
+import org.junit.Test;
+
+import javax.servlet.http.HttpServletRequest;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+public class ParameterNameSecurityGuardTest {
+
+    @Test
+    public void shouldPass() throws Exception {
+        // given
+        SecurityGuard guard = new ParameterNameSecurityGuard();
+
+        HttpServletRequest request = new MockHttpServletRequest();
+
+        // when
+        SecurityPass pass = guard.accept(request);
+
+        // then
+        assertTrue(pass.isAccepted());
+        assertNull(pass.getGuardMessage());
+    }
+
+}

Added: 
struts/struts2/trunk/core/src/test/java/org/apache/struts2/security/ParameterValueSecurityGuardTest.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/java/org/apache/struts2/security/ParameterValueSecurityGuardTest.java?rev=1533336&view=auto
==============================================================================
--- 
struts/struts2/trunk/core/src/test/java/org/apache/struts2/security/ParameterValueSecurityGuardTest.java
 (added)
+++ 
struts/struts2/trunk/core/src/test/java/org/apache/struts2/security/ParameterValueSecurityGuardTest.java
 Fri Oct 18 06:47:31 2013
@@ -0,0 +1,28 @@
+package org.apache.struts2.security;
+
+import com.mockobjects.servlet.MockHttpServletRequest;
+import org.junit.Test;
+
+import javax.servlet.http.HttpServletRequest;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+public class ParameterValueSecurityGuardTest {
+
+    @Test
+    public void shouldPass() throws Exception {
+        // given
+        SecurityGuard guard = new ParameterValueSecurityGuard();
+
+        HttpServletRequest request = new MockHttpServletRequest();
+
+        // when
+        SecurityPass pass = guard.accept(request);
+
+        // then
+        assertTrue(pass.isAccepted());
+        assertNull(pass.getGuardMessage());
+    }
+
+}


Reply via email to