aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Becker2012-01-06 11:49:22 (EST)
committerGreg Wilkins2012-01-08 19:33:06 (EST)
commitc88a4551aea574d84ea7589257137c36e016253a (patch)
treee1ca462cdc8ca3004f71aa8d78ad94b86de6bcd2
parentbbaef55bd61811c9adc4cb21d4c1b42a3c02e999 (diff)
downloadorg.eclipse.jetty.project-c88a4551aea574d84ea7589257137c36e016253a.zip
org.eclipse.jetty.project-c88a4551aea574d84ea7589257137c36e016253a.tar.gz
org.eclipse.jetty.project-c88a4551aea574d84ea7589257137c36e016253a.tar.bz2
366774: NumberFormatException when parsing Host header now causes a 400 return code
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/Request.java20
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java73
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelTimeoutTest.java20
3 files changed, 76 insertions, 37 deletions
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java
index 7a54b62..30dfd68 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java
@@ -46,10 +46,12 @@ import javax.servlet.http.HttpSession;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationListener;
import org.eclipse.jetty.http.HttpCookie;
+import org.eclipse.jetty.http.HttpException;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeaders;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.http.HttpParser;
+import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.http.HttpVersions;
import org.eclipse.jetty.http.MimeTypes;
@@ -1016,7 +1018,23 @@ public class Request implements HttpServletRequest
case ':':
_serverName = BufferUtil.to8859_1_String(hostPort.peek(hostPort.getIndex(),i - hostPort.getIndex()));
- _port = BufferUtil.toInt(hostPort.peek(i + 1,hostPort.putIndex() - i - 1));
+ try
+ {
+ _port = BufferUtil.toInt(hostPort.peek(i + 1,hostPort.putIndex() - i - 1));
+ }
+ catch (NumberFormatException e)
+ {
+ try
+ {
+ if (_connection != null)
+ _connection._generator.sendError(HttpStatus.BAD_REQUEST_400,"Port couldn't be parsed from Host header: " + hostPort,null,
+ true);
+ }
+ catch (IOException e1)
+ {
+ throw new IllegalArgumentException("IOException caught while trying to send error due to invalid host header: " + hostPort,e1);
+ }
+ }
return _serverName;
}
}
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java
index bc4cbff..a81ad64 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java
@@ -40,6 +40,7 @@ import junit.framework.Assert;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
@@ -78,7 +79,7 @@ public class RequestTest
_server.stop();
_server.join();
}
-
+
@Test
public void testParamExtraction() throws Exception
{
@@ -101,27 +102,27 @@ public class RequestTest
System.err.println(map);
assertFalse(map == null);
assertTrue(map.isEmpty());
-
+
Enumeration names = request.getParameterNames();
assertFalse(names.hasMoreElements());
}
-
+
return true;
}
};
-
+
//Send a request with query string with illegal hex code to cause
//an exception parsing the params
String request="GET /?param=%ZZaaa HTTP/1.1\r\n"+
"Host: whatever\r\n"+
"Content-Type: text/html;charset=utf8\n"+
"\n";
-
+
String responses=_connector.getResponses(request);
assertTrue(responses.startsWith("HTTP/1.1 200"));
-
+
}
-
+
@Test
public void testBadUtf8ParamExtraction() throws Exception
{
@@ -133,20 +134,40 @@ public class RequestTest
return value.startsWith("aaa") && value.endsWith("bb");
}
};
-
+
//Send a request with query string with illegal hex code to cause
//an exception parsing the params
String request="GET /?param=aaa%E7bbb HTTP/1.1\r\n"+
"Host: whatever\r\n"+
"Content-Type: text/html;charset=utf8\n"+
"\n";
-
+
String responses=_connector.getResponses(request);
- assertTrue(responses.startsWith("HTTP/1.1 200"));
+ assertTrue(responses.startsWith("HTTP/1.1 200"));
}
-
-
+ @Test
+ public void testInvalidHostHeader() throws Exception
+ {
+ // Use a contextHandler with vhosts to force call to Request.getServerName()
+ ContextHandler handler = new ContextHandler();
+ handler.addVirtualHosts(new String[1]);
+ _server.stop();
+ _server.setHandler(handler);
+ _server.start();
+
+ // Request with illegal Host header
+ String request="GET / HTTP/1.1\r\n"+
+ "Host: whatever.com:\r\n"+
+ "Content-Type: text/html;charset=utf8\n"+
+ "\n";
+
+ String responses=_connector.getResponses(request);
+ assertTrue("400 Bad Request response expected",responses.startsWith("HTTP/1.1 400"));
+ }
+
+
+
@Test
public void testContentTypeEncoding() throws Exception
{
@@ -196,7 +217,7 @@ public class RequestTest
assertTrue(results.get(i++).startsWith("text/html"));
assertEquals(" x=z; ",results.get(i++));
}
-
+
@Test
public void testHostPort() throws Exception
{
@@ -369,7 +390,7 @@ public class RequestTest
Reader reader=request.getReader();
String in = IO.toString(reader);
String param = request.getParameter("param");
-
+
byte[] b=("read='"+in+"' param="+param+"\n").getBytes(StringUtil.__UTF8);
response.setContentLength(b.length);
response.getOutputStream().write(b);
@@ -389,11 +410,11 @@ public class RequestTest
"param=wrong\r\n";
String responses = _connector.getResponses(request);
-
+
assertTrue(responses.indexOf("read='param=wrong' param=right")>0);
-
+
}
-
+
@Test
public void testPartialInput() throws Exception
{
@@ -752,7 +773,7 @@ public class RequestTest
{
_server.setAttribute("org.eclipse.jetty.server.Request.maxFormContentSize",-1);
_server.setAttribute("org.eclipse.jetty.server.Request.maxFormKeys",1000);
-
+
// This file is not distributed - as it is dangerous
File evil_keys = new File("/tmp/keys_mapping_to_zero_2m");
if (!evil_keys.exists())
@@ -760,10 +781,10 @@ public class RequestTest
Log.info("testHashDOS skipped");
return;
}
-
+
BufferedReader in = new BufferedReader(new FileReader(evil_keys));
StringBuilder buf = new StringBuilder(4000000);
-
+
String key=null;
buf.append("a=b");
while((key=in.readLine())!=null)
@@ -771,7 +792,7 @@ public class RequestTest
buf.append("&").append(key).append("=").append("x");
}
buf.append("&c=d");
-
+
_handler._checker = new RequestTester()
{
public boolean check(HttpServletRequest request,HttpServletResponse response)
@@ -787,15 +808,15 @@ public class RequestTest
"Connection: close\r\n"+
"\r\n"+
buf;
-
+
long start=System.currentTimeMillis();
String response = _connector.getResponses(request);
assertTrue(response.contains("200 OK"));
long now=System.currentTimeMillis();
assertTrue((now-start)<5000);
}
-
-
+
+
interface RequestTester
{
boolean check(HttpServletRequest request,HttpServletResponse response) throws IOException;
@@ -812,12 +833,12 @@ public class RequestTest
if (request.getContentLength()>0 && !MimeTypes.FORM_ENCODED.equals(request.getContentType()))
_content=IO.toString(request.getInputStream());
-
+
if (_checker!=null && _checker.check(request,response))
response.setStatus(200);
else
response.sendError(500);
-
+
}
}
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelTimeoutTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelTimeoutTest.java
index c3479cb..b0b3af6 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelTimeoutTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelTimeoutTest.java
@@ -24,14 +24,14 @@ import java.net.Socket;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.util.IO;
-import org.junit.Before;
+import org.junit.BeforeClass;
import org.junit.Test;
public class SelectChannelTimeoutTest extends ConnectorTimeoutTest
{
-
- @Before
- public void init() throws Exception
+
+ @BeforeClass
+ public static void init() throws Exception
{
SelectChannelConnector connector = new SelectChannelConnector();
connector.setMaxIdleTime(MAX_IDLE_TIME); // 250 msec max idle
@@ -52,7 +52,7 @@ public class SelectChannelTimeoutTest extends ConnectorTimeoutTest
_handler.setResumeAfter(25);
assertTrue(process(null).toUpperCase().contains("RESUMED"));
}
-
+
@Test
public void testIdleTimeoutAfterTimeout() throws Exception
{
@@ -62,13 +62,13 @@ public class SelectChannelTimeoutTest extends ConnectorTimeoutTest
session.setHandler(_handler);
_server.setHandler(session);
_server.start();
-
+
_handler.setSuspendFor(50);
assertTrue(process(null).toUpperCase().contains("TIMEOUT"));
}
-
+
@Test
- public void testIdleTimeoutAfterComplete() throws Exception
+ public void testIdleTimeoutAfterComplete() throws Exception
{
SuspendHandler _handler = new SuspendHandler();
_server.stop();
@@ -76,13 +76,13 @@ public class SelectChannelTimeoutTest extends ConnectorTimeoutTest
session.setHandler(_handler);
_server.setHandler(session);
_server.start();
-
+
_handler.setSuspendFor(100);
_handler.setCompleteAfter(25);
assertTrue(process(null).toUpperCase().contains("COMPLETED"));
}
- private synchronized String process(String content) throws UnsupportedEncodingException, IOException, InterruptedException
+ private synchronized String process(String content) throws UnsupportedEncodingException, IOException, InterruptedException
{
String request = "GET / HTTP/1.1\r\n" + "Host: localhost\r\n" + "Connection: close\r\n";