Author: markt Date: Tue Feb 6 14:17:50 2018 New Revision: 1823337 URL: http://svn.apache.org/viewvc?rev=1823337&view=rev Log: Test cases for processing ServletSecurity annotations at web application start
Added: tomcat/trunk/test/javax/servlet/annotation/ tomcat/trunk/test/javax/servlet/annotation/TestServletSecurity.java (with props) tomcat/trunk/test/javax/servlet/annotation/TestServletSecurityMappings.java (with props) Modified: tomcat/trunk/test/org/apache/catalina/core/TestStandardContext.java Added: tomcat/trunk/test/javax/servlet/annotation/TestServletSecurity.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/javax/servlet/annotation/TestServletSecurity.java?rev=1823337&view=auto ============================================================================== --- tomcat/trunk/test/javax/servlet/annotation/TestServletSecurity.java (added) +++ tomcat/trunk/test/javax/servlet/annotation/TestServletSecurity.java Tue Feb 6 14:17:50 2018 @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 javax.servlet.annotation; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.junit.Assert; +import org.junit.Test; + +import org.apache.catalina.Context; +import org.apache.catalina.startup.Tomcat; +import org.apache.catalina.startup.TomcatBaseTest; +import org.apache.tomcat.util.buf.ByteChunk; + +public class TestServletSecurity extends TomcatBaseTest { + + @Test + public void testFooThenFooBar() throws Exception { + doTestFooAndFooBar(true); + } + + + @Test + public void testFooBarThenFoo() throws Exception { + doTestFooAndFooBar(false); + } + + + public void doTestFooAndFooBar(boolean fooFirst) throws Exception { + // Setup Tomcat instance + Tomcat tomcat = getTomcatInstance(); + + // No file system docBase required + Context ctx = tomcat.addContext("", null); + + Tomcat.addServlet(ctx, "Foo", Foo.class.getName()); + ctx.addServletMappingDecoded("/foo/*", "Foo"); + + Tomcat.addServlet(ctx, "FooBar", FooBar.class.getName()); + ctx.addServletMappingDecoded("/foo/bar/*", "FooBar"); + + tomcat.start(); + + ByteChunk bc = new ByteChunk(); + int rc; + + if (fooFirst) { + rc = getUrl("http://localhost:" + getPort() + "/foo", bc, null, null); + } else { + rc = getUrl("http://localhost:" + getPort() + "/foo/bar", bc, null, null); + } + + bc.recycle(); + Assert.assertEquals(403, rc); + + if (fooFirst) { + rc = getUrl("http://localhost:" + getPort() + "/foo/bar", bc, null, null); + } else { + rc = getUrl("http://localhost:" + getPort() + "/foo", bc, null, null); + } + + Assert.assertEquals(403, rc); + } + + + @ServletSecurity(@HttpConstraint(ServletSecurity.EmptyRoleSemantic.DENY)) + public static class Foo extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + resp.getWriter().print("OK: Foo"); + } + } + + + public static class FooBar extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + resp.getWriter().print("OK: FooBar"); + } + } +} Propchange: tomcat/trunk/test/javax/servlet/annotation/TestServletSecurity.java ------------------------------------------------------------------------------ svn:eol-style = native Added: tomcat/trunk/test/javax/servlet/annotation/TestServletSecurityMappings.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/javax/servlet/annotation/TestServletSecurityMappings.java?rev=1823337&view=auto ============================================================================== --- tomcat/trunk/test/javax/servlet/annotation/TestServletSecurityMappings.java (added) +++ tomcat/trunk/test/javax/servlet/annotation/TestServletSecurityMappings.java Tue Feb 6 14:17:50 2018 @@ -0,0 +1,247 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 javax.servlet.annotation; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import javax.servlet.ServletContainerInitializer; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRegistration; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +import org.apache.catalina.Context; +import org.apache.catalina.startup.Tomcat; +import org.apache.catalina.startup.TomcatBaseTest; +import org.apache.tomcat.util.buf.ByteChunk; + +@RunWith(Parameterized.class) +public class TestServletSecurityMappings extends TomcatBaseTest { + + @Parameters(name="{0}, {1}, {2}, {3}") + public static Collection<Object[]> inputs() { + List<Object[]> result = new ArrayList<>(); + result.add(new Object[] { Boolean.FALSE, Boolean.FALSE, Boolean.FALSE, Boolean.FALSE }); + result.add(new Object[] { Boolean.FALSE, Boolean.FALSE, Boolean.FALSE, Boolean.TRUE }); + result.add(new Object[] { Boolean.FALSE, Boolean.FALSE, Boolean.TRUE , Boolean.FALSE }); + result.add(new Object[] { Boolean.FALSE, Boolean.FALSE, Boolean.TRUE, Boolean.TRUE }); + result.add(new Object[] { Boolean.FALSE, Boolean.TRUE, Boolean.FALSE, Boolean.FALSE }); + result.add(new Object[] { Boolean.FALSE, Boolean.TRUE, Boolean.FALSE, Boolean.TRUE }); + result.add(new Object[] { Boolean.FALSE, Boolean.TRUE, Boolean.TRUE , Boolean.FALSE }); + result.add(new Object[] { Boolean.FALSE, Boolean.TRUE, Boolean.TRUE, Boolean.TRUE }); + result.add(new Object[] { Boolean.TRUE, Boolean.FALSE, Boolean.FALSE, Boolean.FALSE }); + result.add(new Object[] { Boolean.TRUE, Boolean.FALSE, Boolean.FALSE, Boolean.TRUE }); + result.add(new Object[] { Boolean.TRUE, Boolean.FALSE, Boolean.TRUE , Boolean.FALSE }); + result.add(new Object[] { Boolean.TRUE, Boolean.FALSE, Boolean.TRUE, Boolean.TRUE }); + result.add(new Object[] { Boolean.TRUE, Boolean.TRUE, Boolean.FALSE, Boolean.FALSE }); + result.add(new Object[] { Boolean.TRUE, Boolean.TRUE, Boolean.FALSE, Boolean.TRUE }); + result.add(new Object[] { Boolean.TRUE, Boolean.TRUE, Boolean.TRUE , Boolean.FALSE }); + result.add(new Object[] { Boolean.TRUE, Boolean.TRUE, Boolean.TRUE, Boolean.TRUE }); + return result; + } + + @Parameter(0) + public boolean redirectContextRoot; + + @Parameter(1) + public boolean secureRoot; + + @Parameter(2) + public boolean secureDefault; + + @Parameter(3) + public boolean secureFoo; + + + @Test + public void doTestSecurityAnnotationsAddServlet() throws Exception { + + // Setup Tomcat instance + Tomcat tomcat = getTomcatInstance(); + + // No file system docBase required + Context ctx = tomcat.addContext("/test", null); + ctx.setMapperContextRootRedirectEnabled(redirectContextRoot); + + ServletContainerInitializer sci = new SCI(secureRoot, secureDefault, secureFoo); + ctx.addServletContainerInitializer(sci, null); + + tomcat.start(); + + ByteChunk bc = new ByteChunk(); + int rc; + + // Foo + rc = getUrl("http://localhost:" + getPort() + "/test/foo", bc, false); + if (secureFoo || secureDefault) { + Assert.assertEquals(403, rc); + } else { + Assert.assertEquals(200, rc); + } + bc.recycle(); + + // Default + rc = getUrl("http://localhost:" + getPort() + "/test/something", bc, false); + if (secureDefault) { + Assert.assertEquals(403, rc); + } else { + Assert.assertEquals(200, rc); + } + bc.recycle(); + + // Root + rc = getUrl("http://localhost:" + getPort() + "/test", bc, false); + if (redirectContextRoot) { + Assert.assertEquals(302, rc); + } else { + if (secureRoot || secureDefault) { + Assert.assertEquals(403, rc); + } else { + Assert.assertEquals(200, rc); + } + } + } + + + public static class SCI implements ServletContainerInitializer { + + private final boolean secureRoot; + private final boolean secureDefault; + private final boolean secureFoo; + + public SCI(boolean secureRoot, boolean secureDefault, boolean secureFoo) { + this.secureRoot = secureRoot; + this.secureDefault = secureDefault; + this.secureFoo = secureFoo; + } + + @Override + public void onStartup(Set<Class<?>> c, ServletContext ctx) + throws ServletException { + + ServletRegistration.Dynamic sr; + if (secureRoot) { + sr = ctx.addServlet("Root", SecureRoot.class.getName()); + } else { + sr =ctx.addServlet("Root", Root.class.getName()); + } + sr.addMapping(""); + + if (secureDefault) { + sr = ctx.addServlet("Default", SecureDefault.class.getName()); + } else { + sr = ctx.addServlet("Default", Default.class.getName()); + } + sr.addMapping("/"); + + if (secureFoo) { + sr = ctx.addServlet("Foo", SecureFoo.class.getName()); + } else { + sr = ctx.addServlet("Foo", Foo.class.getName()); + } + sr.addMapping("/foo"); + } + } + + + @ServletSecurity(@HttpConstraint(ServletSecurity.EmptyRoleSemantic.DENY)) + public static class SecureRoot extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + resp.getWriter().print("OK"); + } + } + + + public static class Root extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + resp.getWriter().print("OK"); + } + } + + + @ServletSecurity(@HttpConstraint(ServletSecurity.EmptyRoleSemantic.DENY)) + public static class SecureDefault extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + resp.getWriter().print("OK"); + } + } + + + public static class Default extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + resp.getWriter().print("OK"); + } + } + + + @ServletSecurity(@HttpConstraint(ServletSecurity.EmptyRoleSemantic.DENY)) + public static class SecureFoo extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + resp.getWriter().print("OK"); + } + } + + + public static class Foo extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + resp.getWriter().print("OK"); + } + } +} Propchange: tomcat/trunk/test/javax/servlet/annotation/TestServletSecurityMappings.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: tomcat/trunk/test/org/apache/catalina/core/TestStandardContext.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/core/TestStandardContext.java?rev=1823337&r1=1823336&r2=1823337&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/catalina/core/TestStandardContext.java (original) +++ tomcat/trunk/test/org/apache/catalina/core/TestStandardContext.java Tue Feb 6 14:17:50 2018 @@ -36,7 +36,10 @@ import javax.servlet.ServletRegistration import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.ServletSecurityElement; +import javax.servlet.annotation.HttpConstraint; +import javax.servlet.annotation.HttpMethodConstraint; import javax.servlet.annotation.MultipartConfig; +import javax.servlet.annotation.ServletSecurity; import javax.servlet.annotation.ServletSecurity.TransportGuarantee; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @@ -990,4 +993,51 @@ public class TestStandardContext extends context.setPath(value); Assert.assertEquals(expectedValue, context.getPath()); } + + + @Test + public void testUncoveredMethods() throws Exception { + // Setup Tomcat instance + Tomcat tomcat = getTomcatInstance(); + + // No file system docBase required + Context ctx = tomcat.addContext("/test", null); + ctx.setDenyUncoveredHttpMethods(true); + + ServletContainerInitializer sci = new SCI(); + ctx.addServletContainerInitializer(sci, null); + + tomcat.start(); + + ByteChunk bc = new ByteChunk(); + int rc; + + rc = getUrl("http://localhost:" + getPort() + "/test/foo", bc, false); + + Assert.assertEquals(403, rc); + } + + + public static class SCI implements ServletContainerInitializer { + @Override + public void onStartup(Set<Class<?>> c, ServletContext ctx) + throws ServletException { + ServletRegistration.Dynamic sr = ctx.addServlet("Foo", Foo.class.getName()); + sr.addMapping("/foo"); + } + } + + + @ServletSecurity(value=@HttpConstraint(ServletSecurity.EmptyRoleSemantic.DENY), + httpMethodConstraints=@HttpMethodConstraint("POST")) + public static class Foo extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + resp.getWriter().print("OK"); + } + } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org