You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by ni...@apache.org on 2006/02/22 04:02:16 UTC

svn commit: r379661 - in /struts/action/trunk/src: java/org/apache/struts/mock/ java/org/apache/struts/util/ test/org/apache/struts/util/

Author: niallp
Date: Tue Feb 21 19:02:14 2006
New Revision: 379661

URL: http://svn.apache.org/viewcvs?rev=379661&view=rev
Log:
Port fix for Bug 38534 from 1.2.x branch - DOS attack, application hack - includes new mock MultipartRequestWrapper implementation and test case submitted by Henri Yandell

Added:
    struts/action/trunk/src/java/org/apache/struts/mock/MockMultipartRequestHandler.java   (with props)
    struts/action/trunk/src/test/org/apache/struts/util/TestRequestUtilsPopulate.java   (with props)
Modified:
    struts/action/trunk/src/java/org/apache/struts/mock/MockHttpServletRequest.java
    struts/action/trunk/src/java/org/apache/struts/util/RequestUtils.java

Modified: struts/action/trunk/src/java/org/apache/struts/mock/MockHttpServletRequest.java
URL: http://svn.apache.org/viewcvs/struts/action/trunk/src/java/org/apache/struts/mock/MockHttpServletRequest.java?rev=379661&r1=379660&r2=379661&view=diff
==============================================================================
--- struts/action/trunk/src/java/org/apache/struts/mock/MockHttpServletRequest.java (original)
+++ struts/action/trunk/src/java/org/apache/struts/mock/MockHttpServletRequest.java Tue Feb 21 19:02:14 2006
@@ -1,7 +1,7 @@
 /*
  * $Id$
  *
- * Copyright 1999-2004 The Apache Software Foundation.
+ * Copyright 1999-2006 The Apache Software Foundation.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -46,8 +46,7 @@
  * <p><strong>WARNING</strong> - Because unit tests operate in a single
  * threaded environment, no synchronization is performed.</p>
  *
- * @version $Rev$ $Date: 2005-11-12 11:52:08 -0500 (Sat, 12 Nov 2005)
- *          $
+ * @version $Rev$ $Date$
  */
 public class MockHttpServletRequest implements HttpServletRequest {
     // ----------------------------------------------------- Instance Variables
@@ -103,6 +102,11 @@
      */
     protected String method = null;
 
+    /**
+     * <p> The Content Type for this request. </p>
+     */
+    protected String contentType = null;
+
     // ----------------------------------------------------------- Constructors
     public MockHttpServletRequest() {
         super();
@@ -157,6 +161,10 @@
         this.method = method;
     }
 
+    public void setContentType(String contentType) {
+        this.contentType = contentType;
+    }
+
     public void setPathElements(String contextPath, String servletPath,
         String pathInfo, String queryString) {
         this.contextPath = contextPath;
@@ -322,7 +330,7 @@
     }
 
     public String getContentType() {
-        throw new UnsupportedOperationException();
+        return (contentType);
     }
 
     public ServletInputStream getInputStream() {

Added: struts/action/trunk/src/java/org/apache/struts/mock/MockMultipartRequestHandler.java
URL: http://svn.apache.org/viewcvs/struts/action/trunk/src/java/org/apache/struts/mock/MockMultipartRequestHandler.java?rev=379661&view=auto
==============================================================================
--- struts/action/trunk/src/java/org/apache/struts/mock/MockMultipartRequestHandler.java (added)
+++ struts/action/trunk/src/java/org/apache/struts/mock/MockMultipartRequestHandler.java Tue Feb 21 19:02:14 2006
@@ -0,0 +1,133 @@
+/*
+ * $Id$ 
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.mock;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import org.apache.struts.action.ActionServlet;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.upload.MultipartRequestHandler;
+
+/**
+ * <p>Mock <strong>MultipartRequestHandler</strong> object for unit tests.</p>
+ *
+ * @version $Rev$
+ */
+public class MockMultipartRequestHandler implements MultipartRequestHandler {
+
+    private ActionServlet servlet;
+    private ActionMapping mapping = new ActionMapping();
+    private Hashtable elements;
+
+    /**
+     * Convienience method to set a reference to a mock
+     * ActionServlet instance.
+     */
+    public void setServlet(ActionServlet servlet) {
+        this.servlet = servlet;
+    }
+
+    /**
+     * Convienience method to set a reference to a mock
+     * ActionMapping instance.
+     */
+    public void setMapping(ActionMapping mapping) {
+        this.mapping = mapping;
+    }
+
+    /**
+     * Get the mock ActionServlet instance
+     */
+    public ActionServlet getServlet() {
+        return this.servlet;
+    }
+
+    /**
+     * Get the ActionMapping instance for this mock request
+     */
+    public ActionMapping getMapping() {
+        return this.mapping;
+    }
+
+    /**
+      * <p>Mock parsing of the ServletInputStream.</p>
+      *
+      * <p>Constructs a <code>Hashtable</code> of elements
+      *    from the HttpServletRequest's parameters - no 
+      *    <code>FormFile</code> elements are created.</p> 
+      */
+    public void handleRequest(HttpServletRequest request) throws ServletException {
+        elements = new Hashtable();
+        Enumeration enum = request.getParameterNames();
+        while(enum.hasMoreElements()) {
+            String key = enum.nextElement().toString();
+            elements.put(key, request.getParameter(key));
+        }
+    }
+
+    /**
+     * This method is called on to retrieve all the text
+     * input elements of the request.
+     *
+     * @return A Hashtable where the keys and values are the names and
+     *  values of the request input parameters
+     */
+    public Hashtable getTextElements() {
+        return this.elements;
+    }
+    
+    /**
+     * <p>This method is called on to retrieve all the FormFile
+     * input elements of the request.</p>
+     *
+     * @return This mock implementation returns an empty 
+     *    <code>Hashtable</code>
+     */
+    public Hashtable getFileElements() {
+        return new Hashtable();
+    }
+
+    /**
+     * This method returns all elements of a multipart request.
+     * @return This mock implementation returns a Hashtable where
+     *   the keys are input names and values are either Strings
+     *   (no FormFile elements)
+     */
+    public Hashtable getAllElements() {
+        return this.elements;
+    }
+
+    /**
+     * Mock <code>rollback()</code> method does nothing.
+     */
+    public void rollback() {
+        // ignore
+    }
+
+    /**
+     * Mock <code>finish()</code> method does nothing.
+     */
+    public void finish() {
+        // ignore
+    }
+
+}
+

Propchange: struts/action/trunk/src/java/org/apache/struts/mock/MockMultipartRequestHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/action/trunk/src/java/org/apache/struts/mock/MockMultipartRequestHandler.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Modified: struts/action/trunk/src/java/org/apache/struts/util/RequestUtils.java
URL: http://svn.apache.org/viewcvs/struts/action/trunk/src/java/org/apache/struts/util/RequestUtils.java?rev=379661&r1=379660&r2=379661&view=diff
==============================================================================
--- struts/action/trunk/src/java/org/apache/struts/util/RequestUtils.java (original)
+++ struts/action/trunk/src/java/org/apache/struts/util/RequestUtils.java Tue Feb 21 19:02:14 2006
@@ -1,7 +1,7 @@
 /*
  * $Id$
  *
- * Copyright 1999-2004 The Apache Software Foundation.
+ * Copyright 1999-2006 The Apache Software Foundation.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -50,8 +50,7 @@
  * <p>General purpose utility methods related to processing a servlet request
  * in the Struts controller framework.</p>
  *
- * @version $Rev$ $Date: 2005-11-09 00:11:45 -0500 (Wed, 09 Nov 2005)
- *          $
+ * @version $Rev$ $Date$
  */
 public class RequestUtils {
     // ------------------------------------------------------- Static Variables
@@ -355,6 +354,11 @@
         String method = request.getMethod();
         boolean isMultipart = false;
 
+        if (bean instanceof ActionForm) {
+            ((ActionForm) bean).setMultipartRequestHandler(null);
+        }
+
+        MultipartRequestHandler multipartHandler = null;
         if ((contentType != null)
             && (contentType.startsWith("multipart/form-data"))
             && (method.equalsIgnoreCase("POST"))) {
@@ -371,14 +375,7 @@
             }
 
             // Obtain a MultipartRequestHandler
-            MultipartRequestHandler multipartHandler =
-                getMultipartHandler(request);
-
-            // Set the multipart request handler for our ActionForm.
-            // If the bean isn't an ActionForm, an exception would have been
-            // thrown earlier, so it's safe to assume that our bean is
-            // in fact an ActionForm.
-            ((ActionForm) bean).setMultipartRequestHandler(multipartHandler);
+            multipartHandler = getMultipartHandler(request);
 
             if (multipartHandler != null) {
                 isMultipart = true;
@@ -453,6 +450,14 @@
             BeanUtils.populate(bean, properties);
         } catch (Exception e) {
             throw new ServletException("BeanUtils.populate", e);
+        } finally {
+            if (multipartHandler != null) {
+                // Set the multipart request handler for our ActionForm.
+                // If the bean isn't an ActionForm, an exception would have been
+                // thrown earlier, so it's safe to assume that our bean is
+                // in fact an ActionForm.
+                ((ActionForm) bean).setMultipartRequestHandler(multipartHandler);
+            }
         }
     }
 

Added: struts/action/trunk/src/test/org/apache/struts/util/TestRequestUtilsPopulate.java
URL: http://svn.apache.org/viewcvs/struts/action/trunk/src/test/org/apache/struts/util/TestRequestUtilsPopulate.java?rev=379661&view=auto
==============================================================================
--- struts/action/trunk/src/test/org/apache/struts/util/TestRequestUtilsPopulate.java (added)
+++ struts/action/trunk/src/test/org/apache/struts/util/TestRequestUtilsPopulate.java Tue Feb 21 19:02:14 2006
@@ -0,0 +1,121 @@
+/*
+ * $Id$ 
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.util;
+
+import javax.servlet.ServletException;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.util.RequestUtils;
+import org.apache.struts.Globals;
+import org.apache.struts.mock.TestMockBase;                                                                                                                       
+import org.apache.struts.mock.MockFormBean;                                                                                                                       
+import org.apache.struts.mock.MockMultipartRequestHandler;                                                                                                                       
+
+/**
+ * Unit tests for the RequestUtil's <code>populate</code> method.
+ *
+ * @version $Rev$
+ */
+public class TestRequestUtilsPopulate extends TestMockBase {
+    
+    /**
+     * Defines the testcase name for JUnit.
+     *
+     * @param theName the testcase's name.
+     */
+    public TestRequestUtilsPopulate(String theName) {
+        super(theName);
+    }
+
+    /**
+     * Start the tests.
+     *
+     * @param theArgs the arguments. Not used
+     */
+    public static void main(String[] theArgs) {
+        junit.awtui.TestRunner.main(
+            new String[] { TestRequestUtilsPopulate.class.getName()});
+    }
+
+    /**
+     * @return a test suite (<code>TestSuite</code>) that includes all methods
+     *         starting with "test"
+     */
+    public static Test suite() {
+        // All methods starting with "test" will be executed in the test suite.
+        return new TestSuite(TestRequestUtilsPopulate.class);
+    }
+
+    public void setUp() {
+        super.setUp();
+    }
+
+    public void tearDown() {
+        super.tearDown();
+    }
+
+    /** 
+     * Ensure that the getMultipartRequestHandler cannot be seen in 
+     * a subclass of ActionForm.
+     *
+     * The purpose of this test is to ensure that Bug #38534 is fixed.
+     *
+     */
+    public void testMultipartVisibility() throws Exception {
+
+        String mockMappingName = "mockMapping";
+        String stringValue     = "Test";
+
+        MockFormBean  mockForm = new MockFormBean();
+        ActionMapping mapping  = new ActionMapping();
+        mapping.setName(mockMappingName);
+
+        // Set up the mock HttpServletRequest
+        request.setMethod("POST");
+        request.setContentType("multipart/form-data");
+        request.setAttribute(Globals.MULTIPART_KEY, MockMultipartRequestHandler.class.getName());
+        request.setAttribute(Globals.MAPPING_KEY, mapping);
+
+        request.addParameter("stringProperty", stringValue);
+        request.addParameter("multipartRequestHandler.mapping.name", "Bad");
+
+        // Check the Mapping/ActionForm before
+        assertNull("Multipart Handler already set",    mockForm.getMultipartRequestHandler());
+        assertEquals("Mapping name not set correctly", mockMappingName, mapping.getName());
+
+        // Try to populate
+        try {
+            RequestUtils.populate(mockForm, request);
+        } catch(ServletException se) {
+            // Expected BeanUtils.populate() to throw a NestedNullException
+            // which gets wrapped in RequestUtils in a ServletException
+            assertEquals("Unexpected type of Exception thrown", "BeanUtils.populate", se.getMessage());
+        }
+
+        // Check the Mapping/ActionForm after
+        assertNotNull("Multipart Handler Missing", mockForm.getMultipartRequestHandler());
+        assertEquals("Mapping name has been modified", mockMappingName, mapping.getName());
+
+    }
+    
+}
+

Propchange: struts/action/trunk/src/test/org/apache/struts/util/TestRequestUtilsPopulate.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/action/trunk/src/test/org/apache/struts/util/TestRequestUtilsPopulate.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org