diff --git a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/ValidUrlRule.java b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/ValidUrlRule.java new file mode 100644 index 00000000000..688859a2adf --- /dev/null +++ b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/ValidUrlRule.java @@ -0,0 +1,113 @@ +// +// ======================================================================== +// 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.rewrite.handler; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.jetty.util.URIUtil; + +/** + * This rule can be used to protect against invalid unicode characters in a url making it into applications. + * + * The logic is as follows. + * + * - if decoded uri character is an iso control character return code/reason + * - if no UnicodeBlock is found for character return code/reason + * - if character is in UnicodeBlock.SPECIALS return code/reason + */ +public class ValidUrlRule extends Rule +{ + String _code = "400"; + String _reason = "Illegal Url"; + + public ValidUrlRule() + { + _handling = true; + _terminating = true; + } + + /* ------------------------------------------------------------ */ + /** + * Sets the response status code. + * + * @param code + * response code + */ + public void setCode(String code) + { + _code = code; + } + + /* ------------------------------------------------------------ */ + /** + * Sets the reason for the response status code. Reasons will only reflect if the code value is greater or equal to 400. + * + * @param reason + */ + public void setReason(String reason) + { + _reason = reason; + } + + @Override + public String matchAndApply(String target, HttpServletRequest request, HttpServletResponse response) throws IOException + { + // best to decide the request uri and validate that + String uri = URIUtil.decodePath(request.getRequestURI()); + + for (int i = 0; i < uri.length(); ++i) + { + if (!isValidChar(uri.charAt(i))) + { + int code = Integer.parseInt(_code); + + // status code 400 and up are error codes so include a reason + if (code >= 400) + { + response.sendError(code,_reason); + } + else + { + response.setStatus(code); + } + + // we have matched, return target and consider it is handled + return target; + } + } + + // we have not matched so return null + return null; + } + + protected boolean isValidChar(char c) + { + Character.UnicodeBlock block = Character.UnicodeBlock.of(c); + + return (!Character.isISOControl(c)) && block != null && block != Character.UnicodeBlock.SPECIALS; + } + + public String toString() + { + return super.toString() + "[" + _code + ":" + _reason + "]"; + } +} diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ValidUrlRuleTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ValidUrlRuleTest.java new file mode 100644 index 00000000000..d765d6ec3e4 --- /dev/null +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ValidUrlRuleTest.java @@ -0,0 +1,82 @@ +// +// ======================================================================== +// 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.rewrite.handler; + +import static org.junit.Assert.assertEquals; +import junit.framework.Assert; + +import org.junit.Before; +import org.junit.Test; + +public class ValidUrlRuleTest extends AbstractRuleTestCase +{ + private ValidUrlRule _rule; + + @Before + public void init() throws Exception + { + start(true); + _rule = new ValidUrlRule(); + } + + @Test + public void testValidUrl() throws Exception + { + _rule.setCode("404"); + _request.setRequestURI("/valid/uri.html"); + + _rule.matchAndApply(_request.getRequestURI(), _request, _response); + + assertEquals(0,_response.getStatus()); + } + + @Test + public void testInvalidUrl() throws Exception + { + _rule.setCode("404"); + _request.setRequestURI("/invalid%0c/uri.html"); + + String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); + + assertEquals(404,_response.getStatus()); + } + + @Test + public void testInvalidUrlWithReason() throws Exception + { + _rule.setCode("405"); + _rule.setReason("foo"); + _request.setRequestURI("/%00/"); + + String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); + + assertEquals(405,_response.getStatus()); + assertEquals("foo",_response.getReason()); + } + + @Test + public void testCharacters() throws Exception + { + // space + Assert.assertTrue( _rule.isValidChar("\u0020".charAt(0))); + // form feed + Assert.assertFalse( _rule.isValidChar("\u000c".charAt(0))); + } +} + diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/MultipartFilterTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/MultipartFilterTest.java index a91ee121974..c6a8be67883 100644 --- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/MultipartFilterTest.java +++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/MultipartFilterTest.java @@ -272,7 +272,9 @@ public class MultipartFilterTest HttpTester.Request request = HttpTester.newRequest(); HttpTester.Response response; - // test GET + tester.setAttribute("fileName", "abc"); + tester.setAttribute("desc", "123"); + tester.setAttribute("title", "ttt"); request.setMethod("POST"); request.setVersion("HTTP/1.0"); request.setHeader("Host","tester"); @@ -311,7 +313,8 @@ public class MultipartFilterTest response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertEquals(HttpServletResponse.SC_OK,response.getStatus()); } - + + @Test public void testLFOnlyRequest() throws Exception { diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/Loader.java b/jetty-util/src/main/java/org/eclipse/jetty/util/Loader.java index 2c25bfc4510..fed6bbcaddf 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/Loader.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/Loader.java @@ -47,7 +47,6 @@ public class Loader { /* ------------------------------------------------------------ */ public static URL getResource(Class loadClass,String name, boolean checkParents) - throws ClassNotFoundException { URL url =null; ClassLoader loader=Thread.currentThread().getContextClassLoader(); diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/MultiPartInputStreamParser.java b/jetty-util/src/main/java/org/eclipse/jetty/util/MultiPartInputStreamParser.java index 7850eed4a5a..520d6c56d52 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/MultiPartInputStreamParser.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/MultiPartInputStreamParser.java @@ -470,7 +470,7 @@ public class MultiPartInputStreamParser byte[] byteBoundary=(boundary+"--").getBytes(StringUtil.__ISO_8859_1); // Get first boundary - String line = ((ReadLineInputStream)_in).readLine(); + String line=((ReadLineInputStream)_in).readLine(); if(line==null || !line.equals(boundary)) { throw new IOException("Missing initial multi part boundary"); @@ -486,14 +486,14 @@ public class MultiPartInputStreamParser MultiMap headers = new MultiMap(); while(true) { - line = ((ReadLineInputStream)_in).readLine(); + line=((ReadLineInputStream)_in).readLine(); - //run out of input: - if (line == null) + //No more input + if(line==null) break outer; //end of headers: - if ("".equals(line)) + if("".equals(line)) break; total += line.length(); @@ -619,7 +619,7 @@ public class MultiPartInputStreamParser if (tmp!=10) _in.reset(); else - state=tmp; + state=tmp; } break; } diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/TypeUtil.java b/jetty-util/src/main/java/org/eclipse/jetty/util/TypeUtil.java index 0d966c72c38..ca1d4dc3a12 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/TypeUtil.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/TypeUtil.java @@ -474,58 +474,6 @@ public class TypeUtil } - /* ------------------------------------------------------------ */ - @Deprecated - public static byte[] readLine(InputStream in) throws IOException - { - byte[] buf = new byte[256]; - - int i=0; - int loops=0; - int ch=0; - - while (true) - { - ch=in.read(); - if (ch<0) - break; - loops++; - - // skip a leading LF's - if (loops==1 && ch==LF) - continue; - - if (ch==CR || ch==LF) - break; - - if (i>=buf.length) - { - byte[] old_buf=buf; - buf=new byte[old_buf.length+256]; - System.arraycopy(old_buf, 0, buf, 0, old_buf.length); - } - buf[i++]=(byte)ch; - } - - if (ch==-1 && i==0) - return null; - - // skip a trailing LF if it exists - if (ch==CR && in.available()>=1 && in.markSupported()) - { - in.mark(1); - ch=in.read(); - if (ch!=LF) - in.reset(); - } - - byte[] old_buf=buf; - buf=new byte[i]; - System.arraycopy(old_buf, 0, buf, 0, i); - - return buf; - } - public static Object call(Class oClass, String methodName, Object obj, Object[] arg) throws InvocationTargetException, NoSuchMethodException { diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/log/Log.java b/jetty-util/src/main/java/org/eclipse/jetty/util/log/Log.java index 19563b4e266..bc54550ffc6 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/log/Log.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/log/Log.java @@ -89,7 +89,7 @@ public class Log * configuration of the Log class in situations where access to the System.properties are * either too late or just impossible. */ - URL testProps = Log.class.getClassLoader().getResource("jetty-logging.properties"); + URL testProps = Loader.getResource(Log.class,"jetty-logging.properties",true); if (testProps != null) { InputStream in = null; @@ -241,7 +241,7 @@ public class Log public static void setLogToParent(String name) { ClassLoader loader = Log.class.getClassLoader(); - if (loader.getParent()!=null) + if (loader!=null && loader.getParent()!=null) { try { diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/resource/Resource.java b/jetty-util/src/main/java/org/eclipse/jetty/util/resource/Resource.java index af1da8291f3..198d8b37072 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/resource/Resource.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/resource/Resource.java @@ -299,16 +299,7 @@ public abstract class Resource implements ResourceFactory URL url=Resource.class.getResource(name); if (url==null) - { - try - { - url=Loader.getResource(Resource.class,name,checkParents); - } - catch(ClassNotFoundException e) - { - url=ClassLoader.getSystemResource(name); - } - } + url=Loader.getResource(Resource.class,name,checkParents); if (url==null) return null; return newResource(url,useCaches); diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/MultiPartInputStreamTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/MultiPartInputStreamTest.java index 31ff1c3f809..f77568c5c4b 100644 --- a/jetty-util/src/test/java/org/eclipse/jetty/util/MultiPartInputStreamTest.java +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/MultiPartInputStreamTest.java @@ -376,7 +376,6 @@ public class MultiPartInputStreamTest assertThat(baos.toString("UTF-8"), is("Other")); } - public void testMulti () throws Exception { diff --git a/jetty-xml/src/main/java/org/eclipse/jetty/xml/XmlConfiguration.java b/jetty-xml/src/main/java/org/eclipse/jetty/xml/XmlConfiguration.java index 820f8e5fcd1..560b0c1e62c 100644 --- a/jetty-xml/src/main/java/org/eclipse/jetty/xml/XmlConfiguration.java +++ b/jetty-xml/src/main/java/org/eclipse/jetty/xml/XmlConfiguration.java @@ -95,32 +95,25 @@ public class XmlConfiguration private synchronized static XmlParser initParser() { XmlParser parser = new XmlParser(); - try - { - URL config60 = Loader.getResource(XmlConfiguration.class,"org/eclipse/jetty/xml/configure_6_0.dtd",true); - URL config76 = Loader.getResource(XmlConfiguration.class,"org/eclipse/jetty/xml/configure_7_6.dtd",true); - URL config90 = Loader.getResource(XmlConfiguration.class,"org/eclipse/jetty/xml/configure_9_0.dtd",true); - parser.redirectEntity("configure.dtd",config90); - parser.redirectEntity("configure_1_0.dtd",config60); - parser.redirectEntity("configure_1_1.dtd",config60); - parser.redirectEntity("configure_1_2.dtd",config60); - parser.redirectEntity("configure_1_3.dtd",config60); - parser.redirectEntity("configure_6_0.dtd",config60); - parser.redirectEntity("configure_7_6.dtd",config76); - parser.redirectEntity("configure_9_0.dtd",config90); + URL config60 = Loader.getResource(XmlConfiguration.class,"org/eclipse/jetty/xml/configure_6_0.dtd",true); + URL config76 = Loader.getResource(XmlConfiguration.class,"org/eclipse/jetty/xml/configure_7_6.dtd",true); + URL config90 = Loader.getResource(XmlConfiguration.class,"org/eclipse/jetty/xml/configure_9_0.dtd",true); + parser.redirectEntity("configure.dtd",config90); + parser.redirectEntity("configure_1_0.dtd",config60); + parser.redirectEntity("configure_1_1.dtd",config60); + parser.redirectEntity("configure_1_2.dtd",config60); + parser.redirectEntity("configure_1_3.dtd",config60); + parser.redirectEntity("configure_6_0.dtd",config60); + parser.redirectEntity("configure_7_6.dtd",config76); + parser.redirectEntity("configure_9_0.dtd",config90); - parser.redirectEntity("http://jetty.mortbay.org/configure.dtd",config90); - parser.redirectEntity("http://jetty.eclipse.org/configure.dtd",config90); - parser.redirectEntity("http://www.eclipse.org/jetty/configure.dtd",config90); + parser.redirectEntity("http://jetty.mortbay.org/configure.dtd",config90); + parser.redirectEntity("http://jetty.eclipse.org/configure.dtd",config90); + parser.redirectEntity("http://www.eclipse.org/jetty/configure.dtd",config90); + + parser.redirectEntity("-//Mort Bay Consulting//DTD Configure//EN",config90); + parser.redirectEntity("-//Jetty//Configure//EN",config90); - parser.redirectEntity("-//Mort Bay Consulting//DTD Configure//EN",config90); - parser.redirectEntity("-//Jetty//Configure//EN",config90); - } - catch (ClassNotFoundException e) - { - LOG.warn(e.toString()); - LOG.debug(e); - } return parser; }