From 5f2e50a0e469fa4695f3634a082dab6357d37219 Mon Sep 17 00:00:00 2001
From: Radko Krkos <krkos@cesnet.cz>
Date: Thu, 16 Aug 2018 11:30:23 +0200
Subject: [PATCH] Server: Prevent reading from wsgi.input past CONTENT-LENGTH
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* WSGI specification is loosely defined, some servers (nginx, wsgi_ref, ...)
  would hang if no payload was present and CONTENT-LENGTH was missing.
* We now implement the correct (more strict) behaviour on application part
  according to specification.

Signed-off-by: Pavel Kácha <ph@cesnet.cz>
---
 warden3/warden_server/warden_server.py | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/warden3/warden_server/warden_server.py b/warden3/warden_server/warden_server.py
index 3a0ba56..4ad293d 100755
--- a/warden3/warden_server/warden_server.py
+++ b/warden3/warden_server/warden_server.py
@@ -922,8 +922,20 @@ class Server(ObjectBase):
 
             args = self.sanitize_args(path, method, args)
 
+            # Based on RFC2616, section 4.4 we SHOULD respond with 400 (bad request) or 411
+            # (length required) if content length was not specified. We choose not to, to
+            # preserve compatibility with clients deployed in the wild, which use POST for
+            # all requests (even those without payload, with no specified content length).
+            # According to PEP3333, section "Input and Error Streams", the application SHOULD
+            # NOT attempt to read more data than specified by CONTENT-LENGTH. As stated in
+            # section "environ Variables", CONTENT-LENGTH may be empty (string) or absent.
             try:
-                post_data = environ['wsgi.input'].read()
+                content_length = int(environ.get('CONTENT-LENGTH', 0))
+            except ValueError:
+                content_length = 0
+
+            try:
+                post_data = environ['wsgi.input'].read(content_length)
             except:
                 raise self.req.error(message="Data read error.", error=408, exc=sys.exc_info())
 
-- 
GitLab