diff --git a/darkhttpd.c b/darkhttpd.c index bcfb248..3d6a4d3 100644 --- a/darkhttpd.c +++ b/darkhttpd.c @@ -1944,13 +1944,20 @@ static int parse_request(struct connection *conn) { for (bound2 = bound1 + 1; (bound2 < conn->request_length) && (conn->request[bound2] != ' ') && - (conn->request[bound2] != '\r'); + (conn->request[bound2] != '\r') && + (conn->request[bound2] != '\n'); bound2++) ; + if (conn->request[bound2] != '\r' && conn->request[bound2] != '\n') + return 0; /* extra tokens after HTTP version */ proto = split_string(conn->request, bound1, bound2); if (strcasecmp(proto, "HTTP/1.1") == 0) conn->conn_close = 0; + else if (strcasecmp(proto, "HTTP/1.0") != 0) { + free(proto); + return 0; /* unknown version or literal space in request-target */ + } free(proto); } @@ -2519,6 +2526,7 @@ static void process_request(struct connection *conn) { num_requests++; if (!parse_request(conn)) { + conn->conn_close = 1; default_reply(conn, 400, "Bad Request", "You sent a request that the server couldn't understand."); } diff --git a/devel/test.py b/devel/test.py index 4e12f69..520fa97 100755 --- a/devel/test.py +++ b/devel/test.py @@ -255,6 +255,7 @@ def setUpModule(): ["invalid up dir", "/../", "assertIsInvalid"], ["fancy invalid up dir", "/./dir/./../../", "assertIsInvalid"], ["ascii nul", "/\x00/", "assertBadRequest"], + ["space in url", "/foo bar", "assertBadRequest"], ["extra slashes 2", "//.d", "assertNotFound"], ["not found", "/not_found.txt", "assertNotFound"], ["not found dir", "/not_found/", "assertNotFound"], @@ -263,6 +264,25 @@ def setUpModule(): ]: makeSimpleCases(*args) +class TestMalformedRequestLine(TestHelper): + def _raw(self, request_line): + c = Conn() + c.s.send((request_line + "\r\n\r\n").encode("utf-8")) + resp = b"" + while True: + signal.alarm(1) + r = c.s.recv(65536) + signal.alarm(0) + if not r: + break + resp += r + c.close() + return resp + + def test_extra_token_after_version(self): + resp = self._raw("GET / HTTP/1.1 HTTP/1.1\r\nConnection: close") + self.assertBadRequest(resp, "/") + class TestDirRedirect(TestHelper): def setUp(self): self.url = "/mydir"