mirror of
https://github.com/jetty/jetty.project.git
synced 2025-03-03 04:19:12 +00:00
366774: NumberFormatException when parsing Host header now causes a 400 return code
This commit is contained in:
parent
bbaef55bd6
commit
c88a4551ae
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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";
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user