diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..231e449a4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +# Java +*.class +*.jar +*.war +*.ear + +# Eclipse +.project +.classpath +.settings + +# Idea +.idea +*.iml +*.iws +*.ipr + +# OS +Thumbs.db +.DS_Store + +# Gradle +.gradle +!gradle-wrapper.jar + +# Maven +target + +# Build +out +build +bin + +# Other +*.log +*.swp +*.bak diff --git a/README b/README.md similarity index 54% rename from README rename to README.md index b82ea7f92..8b31c284c 100644 --- a/README +++ b/README.md @@ -1,10 +1,21 @@ -$Id: README,v 1.18 2003/12/10 01:04:10 husted Exp $ +# STRUTS -STRUTS -====== +![build status](https://circleci.com/gh/kawasima/struts1-forever.png?style=shield&circle-token=8f99c0e6c923ca570acda8c3640446fdacad2a47) -Introduction ------------- +This struts1's fork is for maintenance to fix the vulnerabilities. + +## Requirements + +Original Struts requires Java 1.4 or higher. But struts1-forever requires Java 1.5 or higher. +Because Commons-Beanutils 1.9.2 is used for preventing a dangerous population. + +## Fixed vulnerabilities + +- CVE-2014-0114 +- CVE-2016-1181 +- CVE-2016-1182 + +## Introduction (Original) This subproject contains the source code for the "Struts" application support package, consisting of the following major components: diff --git a/build-tests.xml b/build-tests.xml index 3a0463f47..de6ac7dee 100644 --- a/build-tests.xml +++ b/build-tests.xml @@ -159,6 +159,7 @@ + @@ -795,11 +796,14 @@ + + - + + diff --git a/build.properties.sample b/build.properties.sample index 6fe5306d9..60014425f 100644 --- a/build.properties.sample +++ b/build.properties.sample @@ -90,6 +90,9 @@ xerces.jar=${apache.home}/xerces-1_4_4/xerces.jar # http://www.antlr.org/ antlr.jar = ../../../antlr-2.7.2/antlr.jar +# The JAR file containing the logging package. This is required if you are +# going to execute the "test.junit" target. +log4j.jar=${apache.home}/logging-log4j-1.2.17/dist/lib/log4j-1.2.17.jar # Properties related to optional tasks # ------------------------------------ diff --git a/conf/test/log4j.properties b/conf/test/log4j.properties new file mode 100644 index 000000000..01207fb29 --- /dev/null +++ b/conf/test/log4j.properties @@ -0,0 +1,22 @@ +################################################################################ +## +## Log4j Configuration file. +## +## web.xml of org.springframework.web.util.Log4jConfigListener +## Define the location of the file with the setting. +## +################################################################################ + +# Log4JLogger Initialization parameter setting + +# Log level, appender name setting +log4j.rootCategory=INFO, consoleLog + +# Detailed log level setting +log4j.category.org.apache.struts.utl=DEBUG + +# Console appender setting +log4j.appender.consoleLog=org.apache.log4j.ConsoleAppender +log4j.appender.consoleLog.Target=System.out +log4j.appender.consoleLog.layout=org.apache.log4j.PatternLayout +log4j.appender.consoleLog.layout.ConversionPattern=[%d{yyyy/MM/dd HH:mm:ss}][%p][%c{1}] %m%n \ No newline at end of file diff --git a/project.xml b/pom.xml similarity index 57% rename from project.xml rename to pom.xml index d0b20ccc9..e97093dd4 100644 --- a/project.xml +++ b/pom.xml @@ -1,75 +1,24 @@ - - 3 + + 4.0.0 struts struts struts - 1.2.10-SNAPSHOT + 1.2.10-SNAPSHOT The Apache Software Foundation http://struts.apache.org/ - http://struts.apache.org/images/jakarta-logo.gif - - http://struts.apache.org/struts/images/struts.gif 2000 - org.apache.struts - MVC Web Application Framework - jakarta The core of the Struts framework is a flexible control layer based on standard technologies like Java Servlets, JavaBeans, ResourceBundles, and Extensible Markup Language (XML), as well as various Jakarta Commons packages. Struts encourages application architectures based on the Model 2 approach, a variation of the classic Model-View-Controller (MVC) design paradigm. Struts provides its own Controller component and integrates with other technologies to provide the Model and the View. For the Model, Struts can interact with any standard data access technology, including Enterprise Java Beans, JDBC, and Object Relational Bridge. For the View, Struts works well with JavaServer Pages, including JSTL and JSF, as well as Velocity Templates, XSLT, and other presentation systems. The Struts framework provides the invisible underpinnings every professional web application needs to survive. Struts helps you create an extensible development environment for your application, based on published standards and proven design patterns. http://struts.apache.org/ - http://issues.apache.org/bugzilla/ - struts.apache.org - /www/jakarta.apache.org/struts - /www/apache.mirrors.pair.com/jakarta/struts/ - - scm|svn|http|//svn.apache.org/repos/asf/struts/core/trunk - scm|svn|https|//svn.apache.org/repos/asf/struts/core/trunk - http://svn.apache.org/repos/asf/struts/core/trunk - - - - 1.0.2 - 1.0.2 - STRUTS_1_0_2 - - - 1.1.0 - 1.1.0 - STRUTS_1_1 - - - 1.2.0 - 1.2.0 - STRUTS_1_2_0 - - - 1.2.1 - 1.2.1 - STRUTS_1_2_1 - - - 1.2.2 - 1.2.2 - STRUTS_1_2_2 - - - 1.2.3 - 1.2.3 - STRUTS_1_2_3 - - - 1.2.4 - 1.2.4 - STRUTS_1_2_4 - - - 1.2.5 - 1.2.5 - STRUTS_1_2_5 - - + + ttp://issues.apache.org/bugzilla/ + + Struts User List @@ -193,160 +142,195 @@ commons-beanutils commons-beanutils - 1.7.0 - http://jakarta.apache.org/commons/beanutils.html - - true - true - + 1.11.0 commons-digester commons-digester - 1.6 - http://jakarta.apache.org/commons/digester.html - - true - true - + 1.8.1 commons-fileupload commons-fileupload - 1.0 - http://jakarta.apache.org/commons/fileupload/ - - true - true - + 1.6.0 commons-logging commons-logging - 1.0.4 - http://jakarta.apache.org/commons/logging.html - - true - true - + 1.2 commons-validator commons-validator - 1.1.4 - http://jakarta.apache.org/commons/validator/ - - true - true - + 1.7 oro oro 2.0.7 - http://jakarta.apache.org/oro/ - - true - true - xml-apis xml-apis 2.0.2 - http://xml.apache.org/commons/ - - true - provided - antlr antlr - 2.7.2 - - true - + 2.7.7 + + + org.apache.logging.log4j + log4j-1.2-api + 2.24.3 + test + + + org.apache.logging.log4j + log4j-core + 2.24.3 + test javax.servlet servlet-api 2.2 - - provided - + provided junit junit 3.8.1 - http://www.junit.org - - test - + test cactus cactus - 12-1.4.1 - http://jakarta.apache.org/cactus - - test - + + 13-1.7.2 + test cactus cactus-ant 1.4.1 - http://jakarta.apache.org/cactus - - test - + test xalan xalan - 2.5.1 - http://xml.apache.org/xalan - - compile - + 2.7.3 + compile + - struts-dev@jakarta.apache.org src/share - src/test - - - - - org/apache/struts/action/TestDynaActionForm.java - org/apache/struts/action/TestDynaActionFormClass.java - org/apache/struts/config/TestModuleConfig.java - org/apache/struts/config/TestActionConfigMatcher.java - org/apache/struts/util/Test*.java - - - - ${basedir}/conf/share - org/apache/struts/resources - - **/*.xml - **/*.dtd - - - - ${basedir}/src/test + src/test + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 1.4 + 1.4 + + + + + org.codehaus.mojo + xml-maven-plugin + 1.0 + + + generate-tlds + transform + generate-resources + + + + doc/userGuide + doc/stylesheets/tld.xsl + + struts-bean.xml + struts-html.xml + struts-logic.xml + struts-nested.xml + struts-tiles.xml + + ${project.build.outputDirectory}/META-INF/tlds + + + .tld + + + + + + + + + + org.apache.maven.plugins + maven-resources-plugin + 2.7 + + + copy-resources + copy-resources + compile + + ${project.build.outputDirectory}/org/apache/struts/resources + + + conf/share + + **/*.xml + **/*.dtd + + + + + + + copy-test-resources + copy-resources + test-compile + + ${project.build.testOutputDirectory} + + + src/test + + **/*.xml + + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.18.1 + - **/*.xml + org/apache/struts/action/TestDynaActionForm.java + org/apache/struts/action/TestDynaActionFormClass.java + org/apache/struts/config/TestModuleConfig.java + org/apache/struts/config/TestActionConfigMatcher.java + org/apache/struts/util/Test*.java - - - + + + + @@ -383,4 +367,40 @@ maven-simian-plugin + + + JDK9 + + [9 + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 6 + + + + + + + JDK11 + + [11 + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + + + + + + diff --git a/src/share/org/apache/struts/action/ActionServlet.java b/src/share/org/apache/struts/action/ActionServlet.java index 4920fe512..925af5b63 100755 --- a/src/share/org/apache/struts/action/ActionServlet.java +++ b/src/share/org/apache/struts/action/ActionServlet.java @@ -1,14 +1,14 @@ /* - * $Id$ + * $Id$ * * Copyright 2000-2005 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. @@ -24,10 +24,7 @@ import java.math.BigInteger; import java.net.MalformedURLException; import java.net.URL; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.MissingResourceException; +import java.util.*; import javax.servlet.ServletContext; import javax.servlet.ServletException; @@ -40,6 +37,7 @@ import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.beanutils.ConvertUtils; import org.apache.commons.beanutils.PropertyUtils; +import org.apache.commons.beanutils.SuppressPropertiesBeanIntrospector; import org.apache.commons.beanutils.converters.BigDecimalConverter; import org.apache.commons.beanutils.converters.BigIntegerConverter; import org.apache.commons.beanutils.converters.BooleanConverter; @@ -326,7 +324,7 @@ public void init() throws ServletException { initInternal(); initOther(); initServlet(); - + getServletContext().setAttribute(Globals.ACTION_SERVLET_KEY, this); initModuleConfigFactory(); // Initialize modules as needed @@ -335,7 +333,7 @@ public void init() throws ServletException { initModuleDataSources(moduleConfig); initModulePlugIns(moduleConfig); moduleConfig.freeze(); - + Enumeration names = getServletConfig().getInitParameterNames(); while (names.hasMoreElements()) { String name = (String) names.nextElement(); @@ -350,23 +348,23 @@ public void init() throws ServletException { initModulePlugIns(moduleConfig); moduleConfig.freeze(); } - + this.initModulePrefixes(this.getServletContext()); - + this.destroyConfigDigester(); } catch (UnavailableException ex) { throw ex; } catch (Throwable t) { // The follow error message is not retrieved from internal message - // resources as they may not have been able to have been + // resources as they may not have been able to have been // initialized log.error("Unable to initialize Struts ActionServlet due to an " + "unexpected exception or error thrown, so marking the " + "servlet as unavailable. Most likely, this is due to an " + "incorrect or missing library dependency.", t); throw new UnavailableException(t.getMessage()); - } + } } /** @@ -725,13 +723,13 @@ protected void parseModuleConfigFile(Digester digester, String path) if (url == null) { url = getClass().getResource(path); } - + if (url == null) { String msg = internal.getMessage("configMissing", path); log.error(msg); throw new UnavailableException(msg); } - + InputSource is = new InputSource(url.toExternalForm()); input = url.openStream(); is.setByteStream(input); @@ -1059,6 +1057,14 @@ protected void initInternal() throws ServletException { * @exception ServletException if we cannot initialize these resources */ protected void initOther() throws ServletException { + HashSet suppressProperties = new HashSet(); + suppressProperties.add("class"); + suppressProperties.add("multipartRequestHandler"); + suppressProperties.add("resultValueMap"); + + PropertyUtils.addBeanIntrospector( + new SuppressPropertiesBeanIntrospector(suppressProperties)); + PropertyUtils.clearDescriptors(); String value = null; value = getServletConfig().getInitParameter("config"); diff --git a/src/share/org/apache/struts/config/ActionConfig.java b/src/share/org/apache/struts/config/ActionConfig.java index e77604d09..99636a783 100644 --- a/src/share/org/apache/struts/config/ActionConfig.java +++ b/src/share/org/apache/struts/config/ActionConfig.java @@ -557,7 +557,36 @@ public void setCancellable(boolean cancellable) { } this.cancellable = cancellable; } - + + // 2014/07/02 - security problem patch. + // Author: NTT DATA Corporation + /** + * Accepted page value for multi-page validation.
+ * If two or more page values are accepted, then acceptPage is set minimum of them.
+ * If multi-page validation is not use, acceptPage is not set. Then multi-page validation is disabled. + * @since Struts 1.2.9-sp2 + */ + protected Integer acceptPage = null; + + /** + * Returns accepted page value for multi-page validation. + * + * @return Accepted page value for multi-page validation + * @since Struts 1.2.9-sp2 + */ + public Integer getAcceptPage() { + return acceptPage; + } + + /** + * Set accepted page value for multi-page validation. + * + * @param acceptPage Accepted page value for multi-page validation + * @since Struts 1.2.9-sp2 + */ + public void setAcceptPage(Integer acceptPage) { + this.acceptPage = acceptPage; + } // --------------------------------------------------------- Public Methods @@ -811,6 +840,12 @@ public String toString() { sb.append(validate); sb.append(",cancellable="); sb.append(cancellable); + + // 2014/07/02 - security problem patch. + // Author: NTT DATA Corporation + sb.append(",acceptPage="); + sb.append(acceptPage); + return (sb.toString()); } diff --git a/src/share/org/apache/struts/util/RequestUtils.java b/src/share/org/apache/struts/util/RequestUtils.java index c33902155..0a0605ba2 100644 --- a/src/share/org/apache/struts/util/RequestUtils.java +++ b/src/share/org/apache/struts/util/RequestUtils.java @@ -480,6 +480,14 @@ public static void populate( } else { parameterValue = request.getParameterValues(name); } + + // 2014/05/13 - CVE-2014-0114 security problem patch. + // Author: NTT DATA Corporation + if (stripped.startsWith("class.") || stripped.indexOf(".class.") >= 0) { + // this log output is only for detection of invalid parameters and not an integral part of the bug fix + log.info("ignore parameter: paramName=" + stripped); + continue; + } // Populate parameters, except "standard" struts attributes // such as 'org.apache.struts.action.CANCEL' diff --git a/src/share/org/apache/struts/validator/DynaValidatorForm.java b/src/share/org/apache/struts/validator/DynaValidatorForm.java index 1154d8f42..ac8595d80 100644 --- a/src/share/org/apache/struts/validator/DynaValidatorForm.java +++ b/src/share/org/apache/struts/validator/DynaValidatorForm.java @@ -101,10 +101,14 @@ public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) String validationKey = getValidationKey(mapping, request); + // 2014/07/02 - security problem patch. + // Author: NTT DATA Corporation + int validationPage = determinePage(mapping, request); + Validator validator = Resources.initValidator(validationKey, this, application, request, - errors, page); + errors, validationPage); try { validatorResults = validator.validate(); @@ -115,6 +119,24 @@ public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) return errors; } + // 2014/07/02 - security problem patch. + // Author: NTT DATA Corporation + /** + * Determine validation page.
+ * If acceptPage of ActionMapping is null, then returns Integer.MAX_VALUE. + * (multi-page validation is disabled. All validation fields are enabled.)
+ * If page property is less than acceptPage of ActionMapping, returns acceptPage value.
+ * If page property is greater than or equal to acceptPage of ActionMapping, returns page property value. + * @param mapping The mapping used to select this instance. + * @param request The servlet request we are processing. + * @return validation page. + * @since Struts 1.2.9-sp2 + */ + protected int determinePage(ActionMapping mapping, HttpServletRequest request) { + Integer acceptPage = mapping.getAcceptPage(); + return acceptPage != null ? Math.max(acceptPage.intValue(), page) : Integer.MAX_VALUE; + } + /** * Returns the Validation key. * diff --git a/src/share/org/apache/struts/validator/ValidatorForm.java b/src/share/org/apache/struts/validator/ValidatorForm.java index a0c1ca2a6..73750eca3 100644 --- a/src/share/org/apache/struts/validator/ValidatorForm.java +++ b/src/share/org/apache/struts/validator/ValidatorForm.java @@ -100,11 +100,15 @@ public ActionErrors validate(ActionMapping mapping, ActionErrors errors = new ActionErrors(); String validationKey = getValidationKey(mapping, request); + + // 2014/07/02 - security problem patch. + // Author: NTT DATA Corporation + int validationPage = determinePage(mapping, request); Validator validator = Resources.initValidator(validationKey, this, application, request, - errors, page); + errors, validationPage); try { validatorResults = validator.validate(); @@ -114,6 +118,24 @@ public ActionErrors validate(ActionMapping mapping, return errors; } + + // 2014/07/02 - security problem patch. + // Author: NTT DATA Corporation + /** + * Determine validation page.
+ * If acceptPage of ActionMapping is null, then returns Integer.MAX_VALUE. + * (multi-page validation is disabled. All validation fields are enabled.)
+ * If page property is less than acceptPage of ActionMapping, returns acceptPage value.
+ * If page property is greater than or equal to acceptPage of ActionMapping, returns page property value. + * @param mapping The mapping used to select this instance. + * @param request The servlet request we are processing. + * @return validation page. + * @since Struts 1.2.9-sp2 + */ + protected int determinePage(ActionMapping mapping, HttpServletRequest request) { + Integer acceptPage = mapping.getAcceptPage(); + return acceptPage != null ? Math.max(acceptPage.intValue(), page) : Integer.MAX_VALUE; + } /** * Returns the Validation key. diff --git a/src/test/org/apache/struts/config/TestActionConfig.java b/src/test/org/apache/struts/config/TestActionConfig.java new file mode 100644 index 000000000..fa63e3250 --- /dev/null +++ b/src/test/org/apache/struts/config/TestActionConfig.java @@ -0,0 +1,93 @@ +/* + * Copyright 2004 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.config; + +import junit.framework.Test; +import junit.framework.TestSuite; + +import org.apache.struts.mock.TestMockBase; + +public class TestActionConfig extends TestMockBase { + + /** + * Defines the testcase name for JUnit. + * + * @param theName the testcase's name. + */ + public TestActionConfig(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[] {TestActionConfig.class.getName()}); + } + + /** + * @return a test suite (TestSuite) 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(TestActionConfig.class); + } + + public void setUp() { + super.setUp(); + } + + public void tearDown() { + super.tearDown(); + } + + /** + * Test getter of acceptPage property. + */ + public void testGetAcceptPage() { + ActionConfig config = new ActionConfig(); + config.setAcceptPage(new Integer(0)); + Integer acceptPage = config.getAcceptPage(); + assertEquals(new Integer(0), acceptPage); + } + + /** + * Test setter of acceptPage property. + */ + public void testSetAcceptPage() { + ActionConfig config = new ActionConfig(); + config.setAcceptPage(new Integer(0)); + Integer acceptPage = config.getAcceptPage(); + assertEquals(new Integer(0), acceptPage); + } + + /** + * Test a String object representing the value of the ActionConfig object. + */ + public void testToString() { + ActionConfig config = new ActionConfig(); + Integer acceptPage = new Integer(0); + config.setAcceptPage(acceptPage); + String suffix = "acceptPage=0"; + assertTrue(config.toString().endsWith(suffix)); + } + +} diff --git a/src/test/org/apache/struts/mock/MockMultipartRequestHandler.java b/src/test/org/apache/struts/mock/MockMultipartRequestHandler.java index feb2c65ef..0603f8e27 100644 --- a/src/test/org/apache/struts/mock/MockMultipartRequestHandler.java +++ b/src/test/org/apache/struts/mock/MockMultipartRequestHandler.java @@ -88,9 +88,9 @@ public ActionMapping getMapping() { */ public void handleRequest(HttpServletRequest request) throws ServletException { elements = new Hashtable(); - Enumeration enum = request.getParameterNames(); - while (enum.hasMoreElements()) { - String key = enum.nextElement().toString(); + Enumeration e = request.getParameterNames(); + while (e.hasMoreElements()) { + String key = e.nextElement().toString(); elements.put(key, request.getParameter(key)); } } diff --git a/src/test/org/apache/struts/util/TestRequestUtilsPopulate.java b/src/test/org/apache/struts/util/TestRequestUtilsPopulate.java index 3ba48e519..8430c65ba 100644 --- a/src/test/org/apache/struts/util/TestRequestUtilsPopulate.java +++ b/src/test/org/apache/struts/util/TestRequestUtilsPopulate.java @@ -24,7 +24,6 @@ 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; @@ -116,6 +115,137 @@ public void testMultipartVisibility() throws Exception { assertEquals("Mapping name has been modified", mockMappingName, mapping.getName()); } + + /** + * Ensure that the parameter of HTTP request + * which causes ClassLoader manipulation is ignored. + * + * The purpose of this test is to ensure that security problem + * CVE-2014-0114 is fixed. + * + */ + public void testRequestParameterIgnore1() throws Exception { + + String stringValue = "Test"; + + MockFormBean mockForm = new MockFormBean(); + + // Set up the mock HttpServletRequest + request.setMethod("GET"); + request.setContentType(""); + + request.addParameter("class.xxx.case1", stringValue); + + // Try to populate + try { + RequestUtils.populate(mockForm, request); + } catch(ServletException se) { + fail("Occur exception."); + } + + // Check that "class." prefix parameter was ignored + assertNull("ActionForm property set", mockForm.getStringProperty()); + + } + + /** + * Ensure that the parameter of HTTP request + * which causes ClassLoader manipulation is ignored. + * + * The purpose of this test is to ensure that security problem + * CVE-2014-0114 is fixed. + * + */ + public void testRequestParameterIgnore2() throws Exception { + + String stringValue = "Test"; + + MockFormBean mockForm = new MockFormBean(); + + // Set up the mock HttpServletRequest + request.setMethod("GET"); + request.setContentType(""); + + request.addParameter("xxx.class.case2", stringValue); + + // Try to populate + try { + RequestUtils.populate(mockForm, request); + } catch(ServletException se) { + fail("Occur exception."); + } + + // Check that ".class." containing parameter was ignored + assertNull("ActionForm property set", mockForm.getStringProperty()); + + } + + /** + * Ensure that the parameter of HTTP request + * which causes ClassLoader manipulation is ignored. + * + * The purpose of this test is to ensure that security problem + * CVE-2014-0114 is fixed. + * + */ + public void testRequestParameterIgnore3() throws Exception { + + String stringValue = "Test"; + + MockFormBean mockForm = new MockFormBean(); + + // Set up the mock HttpServletRequest + request.setMethod("GET"); + request.setContentType(""); + + request.addParameter("stringProperty", stringValue); + + // Try to populate + try { + RequestUtils.populate(mockForm, request); + } catch(ServletException se) { + fail("Occur exception."); + } + + // Check that normal parameter was NOT ignored + assertEquals("ActionForm property not equal", stringValue, mockForm.getStringProperty()); + + } + + /** + * Ensure that the parameter of HTTP request + * which causes ClassLoader manipulation is ignored. + * + * The purpose of this test is to ensure that security problem + * CVE-2014-0114 is fixed. + * + */ + public void testRequestParameterIgnore4() throws Exception { + + String stringValue = "Test"; + + MockFormBean mockForm = new MockFormBean(); + + // Set up the mock HttpServletRequest + request.setMethod("GET"); + request.setContentType(""); + + request.addParameter("class.xxx.case4", stringValue); + request.addParameter("xxx.class.case4", stringValue); + request.addParameter("stringProperty", stringValue); + + // Try to populate + try { + RequestUtils.populate(mockForm, request); + } catch(ServletException se) { + fail("Occur exception."); + } + + // Check that dangerous parameters were ignored but normal one was populated + assertEquals("ActionForm property not equal", stringValue, mockForm.getStringProperty()); + + } + } diff --git a/src/test/org/apache/struts/validator/TestDynaValidatorForm.java b/src/test/org/apache/struts/validator/TestDynaValidatorForm.java new file mode 100644 index 000000000..1e32e5bc6 --- /dev/null +++ b/src/test/org/apache/struts/validator/TestDynaValidatorForm.java @@ -0,0 +1,119 @@ +/* + * Copyright 2004 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.validator; + +import junit.framework.Test; +import junit.framework.TestSuite; + +import org.apache.struts.action.ActionMapping; +import org.apache.struts.mock.TestMockBase; + +public class TestDynaValidatorForm extends TestMockBase { + + /** + * Defines the testcase name for JUnit. + * + * @param theName the testcase's name. + */ + public TestDynaValidatorForm(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[] {TestDynaValidatorForm.class.getName()}); + } + + /** + * @return a test suite (TestSuite) that includes all methods + * starting with "test" + */ + public static Test suite() { + return new TestSuite(TestDynaValidatorForm.class); + } + + public void setUp() { + super.setUp(); + } + + public void tearDown() { + super.tearDown(); + } + + /** + * Test value of determine page. + */ + public void testDeterminePage01() { + DynaValidatorForm validatorForm = new DynaValidatorForm(); + ActionMapping mapping = new ActionMapping(); + + mapping.setAcceptPage(null); + validatorForm.setPage(-1); + int page = validatorForm.determinePage(mapping, null); + + assertEquals(Integer.MAX_VALUE, page); + } + + /** + * Test value of determine page. + */ + public void testDeterminePage02() { + DynaValidatorForm validatorForm = new DynaValidatorForm(); + ActionMapping mapping = new ActionMapping(); + + mapping.setAcceptPage(new Integer(-1)); + validatorForm.setPage(-1); + int page = validatorForm.determinePage(mapping, null); + + assertEquals(-1, page); + } + + /** + * Test value of determine page. + */ + public void testDeterminePage03() { + DynaValidatorForm validatorForm = new DynaValidatorForm(); + ActionMapping mapping = new ActionMapping(); + + mapping.setAcceptPage(new Integer(-1)); + validatorForm.setPage(0); + int page = validatorForm.determinePage(mapping, null); + + assertEquals(0, page); + } + + /** + * Test value of determine page. + */ + public void testDeterminePage04() { + DynaValidatorForm validatorForm = new DynaValidatorForm(); + ActionMapping mapping = new ActionMapping(); + + mapping.setAcceptPage(new Integer(-1)); + validatorForm.setPage(1); + int page = validatorForm.determinePage(mapping, null); + + assertEquals(1, page); + } + +} + diff --git a/src/test/org/apache/struts/validator/TestValidatorForm.java b/src/test/org/apache/struts/validator/TestValidatorForm.java new file mode 100644 index 000000000..6da3009ab --- /dev/null +++ b/src/test/org/apache/struts/validator/TestValidatorForm.java @@ -0,0 +1,119 @@ +/* + * Copyright 2004 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.validator; + +import junit.framework.Test; +import junit.framework.TestSuite; + +import org.apache.struts.action.ActionMapping; +import org.apache.struts.mock.TestMockBase; + +public class TestValidatorForm extends TestMockBase { + + /** + * Defines the testcase name for JUnit. + * + * @param theName the testcase's name. + */ + public TestValidatorForm(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[] {TestValidatorForm.class.getName()}); + } + + /** + * @return a test suite (TestSuite) that includes all methods + * starting with "test" + */ + public static Test suite() { + return new TestSuite(TestValidatorForm.class); + } + + public void setUp() { + super.setUp(); + } + + public void tearDown() { + super.tearDown(); + } + + /** + * Test value of determine page. + */ + public void testDeterminePage01() { + DynaValidatorForm validatorForm = new DynaValidatorForm(); + ActionMapping mapping = new ActionMapping(); + + mapping.setAcceptPage(null); + validatorForm.setPage(-1); + int page = validatorForm.determinePage(mapping, null); + + assertEquals(Integer.MAX_VALUE, page); + } + + /** + * Test value of determine page. + */ + public void testDeterminePage02() { + DynaValidatorForm validatorForm = new DynaValidatorForm(); + ActionMapping mapping = new ActionMapping(); + + mapping.setAcceptPage(new Integer(-1)); + validatorForm.setPage(-1); + int page = validatorForm.determinePage(mapping, null); + + assertEquals(-1, page); + } + + /** + * Test value of determine page. + */ + public void testDeterminePage03() { + DynaValidatorForm validatorForm = new DynaValidatorForm(); + ActionMapping mapping = new ActionMapping(); + + mapping.setAcceptPage(new Integer(-1)); + validatorForm.setPage(0); + int page = validatorForm.determinePage(mapping, null); + + assertEquals(0, page); + } + + /** + * Test value of determine page. + */ + public void testDeterminePage04() { + DynaValidatorForm validatorForm = new DynaValidatorForm(); + ActionMapping mapping = new ActionMapping(); + + mapping.setAcceptPage(new Integer(-1)); + validatorForm.setPage(1); + int page = validatorForm.determinePage(mapping, null); + + assertEquals(1, page); + } + +} +