Merge branch 'jetty-7' into jetty-8

This commit is contained in:
Joakim Erdfelt 2012-12-27 14:22:57 -07:00
commit 9fde0c56ab
8 changed files with 394 additions and 6 deletions

View File

@ -22,9 +22,9 @@ import static org.junit.Assert.assertEquals;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
@SuppressWarnings("unused")
public class ValidUrlRuleTest extends AbstractRuleTestCase
{
private ValidUrlRule _rule;
@ -89,7 +89,7 @@ public class ValidUrlRuleTest extends AbstractRuleTestCase
{
_rule.setCode("405");
_rule.setReason("foo");
_request.setRequestURI("/jsp/shamrock-%002618.jsp");
_request.setRequestURI("/jsp/shamrock-%00%E2%98%98.jsp");
String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response);
@ -97,13 +97,12 @@ public class ValidUrlRuleTest extends AbstractRuleTestCase
assertEquals("foo",_response.getReason());
}
@Ignore("Not passing (yet), issue in uri decoding")
@Test
public void testValidShamrock() throws Exception
{
_rule.setCode("405");
_rule.setReason("foo");
_request.setRequestURI("/jsp/shamrock-%00%E2%98%98.jsp");
_request.setRequestURI("/jsp/shamrock-%E2%98%98.jsp");
String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response);

View File

@ -75,6 +75,37 @@ public class FileResource extends URLResource
return __checkAliases;
}
/**
* Perform some basic validation of the characters in the string for invalid
* codepoints and null characters.
*
* @param str the string to validate
* @throws URISyntaxException thrown if invalid characters are encountered
*/
private static final String validateUri(String str) throws URISyntaxException
{
if (str == null)
{
return str;
}
int len = str.length();
int codepoint;
for (int i = 0; i < len; i++)
{
codepoint = str.codePointAt(i);
if (codepoint == 0)
{
throw new URISyntaxException(str,"Encountered NULL character");
}
if (Character.isISOControl(codepoint))
{
throw new URISyntaxException(str,"Encountered ISO Control Code");
}
}
return str;
}
/* -------------------------------------------------------- */
public FileResource(URL url)
throws IOException, URISyntaxException
@ -84,8 +115,23 @@ public class FileResource extends URLResource
try
{
// Try standard API to convert URL to file.
/* Note:
* If the passed in URL has a null at the end of the string, then
* url.toExternalForm() and url.toString() strip that knowledge out.
* Which can lead to false positives for .exists() calls.
*
* The URL should be validated in parts, then passed to the File object.
*/
validateUri(url.getFile());
validateUri(url.getPath());
_file =new File(new URI(url.toString()));
}
catch (URISyntaxException e)
{
throw e;
}
catch (Exception e)
{
LOG.ignore(e);
@ -98,7 +144,7 @@ public class FileResource extends URLResource
if (uri.getAuthority()==null)
_file = new File(uri);
else
_file = new File("//"+uri.getAuthority()+URIUtil.decodePath(url.getFile()));
_file = new File(validateUri("//"+uri.getAuthority()+URIUtil.decodePath(url.getFile())));
}
catch (Exception e2)
{

View File

@ -0,0 +1,97 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.util.resource;
import static org.hamcrest.Matchers.*;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import org.eclipse.jetty.toolchain.test.TestingDir;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.UrlEncoded;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
public class FileResourceTest
{
@Rule
public TestingDir testdir = new TestingDir();
private URI createDummyFile(String name) throws IOException
{
File file = testdir.getFile(name);
file.createNewFile();
return file.toURI();
}
private URL decode(URL url) throws MalformedURLException
{
String raw = url.toExternalForm();
String decoded = UrlEncoded.decodeString(raw,0,raw.length(),StringUtil.__UTF8);
return new URL(decoded);
}
@Test
public void testExist_Normal() throws Exception
{
createDummyFile("a.jsp");
URI ref = testdir.getDir().toURI().resolve("a.jsp");
FileResource fileres = new FileResource(decode(ref.toURL()));
Assert.assertThat("FileResource: " + fileres,fileres.exists(),is(true));
}
@Ignore("Cannot get null to be seen by FileResource")
@Test
public void testExist_BadNull() throws Exception
{
createDummyFile("a.jsp");
try {
// request with null at end
URI ref = testdir.getDir().toURI().resolve("a.jsp%00");
FileResource fileres = new FileResource(decode(ref.toURL()));
Assert.assertThat("FileResource: " + fileres,fileres.exists(),is(false));
} catch(URISyntaxException e) {
// Valid path
}
}
@Test
public void testExist_BadNullX() throws Exception
{
createDummyFile("a.jsp");
try {
// request with null and x at end
URI ref = testdir.getDir().toURI().resolve("a.jsp%00x");
FileResource fileres = new FileResource(decode(ref.toURL()));
Assert.assertThat("FileResource: " + fileres,fileres.exists(),is(false));
} catch(URISyntaxException e) {
// Valid path
}
}
}

View File

@ -201,7 +201,7 @@
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>

View File

@ -77,6 +77,13 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<forkMode>always</forkMode>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
@ -105,11 +112,26 @@
<artifactId>jetty-monitor</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-test-helper</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jsp</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>test-webapp-rfc2616</artifactId>

View File

@ -0,0 +1,180 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.test.jsp;
import static org.hamcrest.Matchers.*;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import org.apache.jasper.servlet.JspServlet;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.IO;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
public class JspMatchingTest
{
private static Server server;
private static URI serverURI;
@BeforeClass
public static void startServer() throws Exception
{
server = new Server();
SelectChannelConnector connector = new SelectChannelConnector();
connector.setPort(0);
server.addConnector(connector);
// Configure LoginService
HashLoginService login = new HashLoginService();
login.setName("Test Realm");
File realmFile = MavenTestingUtils.getTestResourceFile("realm.properties");
login.setConfig(realmFile.getAbsolutePath());
server.addBean(login);
// Configure WebApp
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
File webappBase = MavenTestingUtils.getTestResourceDir("docroots/jsp");
context.setResourceBase(webappBase.getAbsolutePath());
context.setClassLoader(Thread.currentThread().getContextClassLoader());
// add default servlet
ServletHolder defaultServHolder = context.addServlet(DefaultServlet.class, "/");
defaultServHolder.setInitParameter("aliases", "true"); // important!
// add jsp
ServletHolder jsp = context.addServlet(JspServlet.class,"*.jsp");
jsp.setInitParameter("classpath", context.getClassPath());
// add context
server.setHandler(context);
server.start();
serverURI = new URI("http://localhost:" + connector.getLocalPort() + "/");
}
@AfterClass
public static void stopServer() throws Exception
{
server.stop();
}
@Test
public void testGetBeanRef() throws Exception
{
URI uri = serverURI.resolve("/dump.jsp");
HttpURLConnection conn = null;
try
{
conn = (HttpURLConnection)uri.toURL().openConnection();
conn.setConnectTimeout(1000);
conn.setReadTimeout(1000);
Assert.assertThat(conn.getResponseCode(),is(200));
System.err.printf("Response Code: %d%n", conn.getResponseCode());
// make sure that jsp actually ran, and didn't just get passed onto
// the default servlet to return the jsp source
String body = getResponseBody(conn);
Assert.assertThat("Body", body, not(containsString("<%@")));
Assert.assertThat("Body", body, not(containsString("<jsp:")));
}
finally
{
close(conn);
}
}
@Test
public void testGetBeanRefInvalid_null() throws Exception
{
URI uri = serverURI.resolve("/dump.jsp%00");
HttpURLConnection conn = null;
try
{
conn = (HttpURLConnection)uri.toURL().openConnection();
conn.setConnectTimeout(1000);
conn.setReadTimeout(1000);
Assert.assertThat(conn.getResponseCode(),is(404));
System.err.printf("Response Code: %d%n", conn.getResponseCode());
}
finally
{
close(conn);
}
}
@Test
public void testGetBeanRefInvalid_nullx() throws Exception
{
URI uri = serverURI.resolve("/dump.jsp%00x");
HttpURLConnection conn = null;
try
{
conn = (HttpURLConnection)uri.toURL().openConnection();
conn.setConnectTimeout(1000);
conn.setReadTimeout(1000);
Assert.assertThat(conn.getResponseCode(),is(404));
System.err.printf("Response Code: %d%n", conn.getResponseCode());
}
finally
{
close(conn);
}
}
protected String getResponseBody(HttpURLConnection conn) throws IOException
{
InputStream in = null;
try
{
in = conn.getInputStream();
return IO.toString(in);
}
finally
{
IO.close(in);
}
}
private void close(HttpURLConnection conn)
{
conn.disconnect();
}
}

View File

@ -0,0 +1,23 @@
<html><head>
<%@ page import="java.util.Enumeration" %>
</head><body>
<h1>JSP Dump</h1>
<table border="1">
<tr><th>Request URI:</th><td><%= request.getRequestURI() %></td></tr>
<tr><th>ServletPath:</th><td><%= request.getServletPath() %></td></tr>
<tr><th>PathInfo:</th><td><%= request.getPathInfo() %></td></tr>
<%
Enumeration e =request.getParameterNames();
while(e.hasMoreElements())
{
String name = (String)e.nextElement();
%>
<tr>
<th>getParameter("<%= name %>")</th>
<td><%= request.getParameter(name) %></td></tr>
<% } %>
</table>
</body></html>

View File

@ -0,0 +1,21 @@
#
# This file defines users passwords and roles for a HashUserRealm
#
# The format is
# <username>: <password>[,<rolename> ...]
#
# Passwords may be clear text, obfuscated or checksummed. The class
# org.eclipse.util.Password should be used to generate obfuscated
# passwords or password checksums
#
# If DIGEST Authentication is used, the password must be in a recoverable
# format, either plain text or OBF:.
#
jetty: MD5:164c88b302622e17050af52c89945d44,user
admin: CRYPT:adpexzg3FUZAk,server-administrator,content-administrator,admin
other: OBF:1xmk1w261u9r1w1c1xmq,user
plain: plain,user
user: password,user
# This entry is for digest auth. The credential is a MD5 hash of username:realmname:password
digest: MD5:6e120743ad67abfbc385bc2bb754e297,user