diff options
author | Tres Seaver <tseaver@palladion.com> | 2014-03-10 12:06:52 -0400 |
---|---|---|
committer | Tres Seaver <tseaver@palladion.com> | 2014-03-10 12:06:52 -0400 |
commit | ab015fd0b9e28ecf1adada6e53e2f66c3925b301 (patch) | |
tree | 8b0361588e6eb6c2179823d085a0ddc12d410b1d | |
parent | 486315c33ecbbc19f29a8947615e8ecabfc6ad6c (diff) | |
download | waitress-ab015fd0b9e28ecf1adada6e53e2f66c3925b301.tar.gz |
Only allow trustted proxies to overried request.urlscheme.
-rw-r--r-- | waitress/task.py | 8 | ||||
-rw-r--r-- | waitress/tests/test_task.py | 24 |
2 files changed, 28 insertions, 4 deletions
diff --git a/waitress/task.py b/waitress/task.py index 7dcd8a4..e28df4c 100644 --- a/waitress/task.py +++ b/waitress/task.py @@ -483,10 +483,14 @@ class WSGITask(Task): environ['SCRIPT_NAME'] = url_prefix environ['PATH_INFO'] = path environ['QUERY_STRING'] = request.query - environ['REMOTE_ADDR'] = channel.addr[0] + host = environ['REMOTE_ADDR'] = channel.addr[0] headers = dict(request.headers) - wsgi_url_scheme = headers.pop('X_FORWARDED_PROTO', request.url_scheme) + if host == server.adj.trusted_proxy: + wsgi_url_scheme = headers.pop('X_FORWARDED_PROTO', + request.url_scheme) + else: + wsgi_url_scheme = request.url_scheme if wsgi_url_scheme not in ('http', 'https'): raise ValueError('Invalid X_FORWARDED_PROTO value') for key, value in headers.items(): diff --git a/waitress/tests/test_task.py b/waitress/tests/test_task.py index 8abb1e5..14a84f3 100644 --- a/waitress/tests/test_task.py +++ b/waitress/tests/test_task.py @@ -650,9 +650,26 @@ class TestWSGITask(unittest.TestCase): self.assertEqual(environ['wsgi.input'], 'stream') self.assertEqual(inst.environ, environ) - def test_get_environment_values_w_scheme_override(self): + def test_get_environment_values_w_scheme_override_untrusted(self): + inst = self._makeOne() + request = DummyParser() + request.headers = { + 'CONTENT_TYPE': 'abc', + 'CONTENT_LENGTH': '10', + 'X_FOO': 'BAR', + 'X_FORWARDED_PROTO': 'https', + 'CONNECTION': 'close', + } + request.query = 'abc' + inst.request = request + environ = inst.get_environment() + self.assertEqual(environ['wsgi.url_scheme'], 'http') + + def test_get_environment_values_w_scheme_override_trusted(self): import sys inst = self._makeOne() + inst.channel.addr = ['192.168.1.1'] + inst.channel.server.adj.trusted_proxy = '192.168.1.1' request = DummyParser() request.headers = { 'CONTENT_TYPE': 'abc', @@ -683,7 +700,7 @@ class TestWSGITask(unittest.TestCase): self.assertEqual(environ['HTTP_CONNECTION'], 'close') self.assertEqual(environ['PATH_INFO'], '/') self.assertEqual(environ['QUERY_STRING'], 'abc') - self.assertEqual(environ['REMOTE_ADDR'], '127.0.0.1') + self.assertEqual(environ['REMOTE_ADDR'], '192.168.1.1') self.assertEqual(environ['CONTENT_TYPE'], 'abc') self.assertEqual(environ['CONTENT_LENGTH'], '10') self.assertEqual(environ['HTTP_X_FOO'], 'BAR') @@ -698,6 +715,8 @@ class TestWSGITask(unittest.TestCase): def test_get_environment_values_w_bogus_scheme_override(self): inst = self._makeOne() + inst.channel.addr = ['192.168.1.1'] + inst.channel.server.adj.trusted_proxy = '192.168.1.1' request = DummyParser() request.headers = { 'CONTENT_TYPE': 'abc', @@ -817,6 +836,7 @@ class DummyAdj(object): host = '127.0.0.1' port = 80 url_prefix = '' + trusted_proxy = None class DummyServer(object): server_name = 'localhost' |