[CalendarServer-changes] [5608] CalendarServer/trunk/twistedcaldav/client
source_changes at macosforge.org
source_changes at macosforge.org
Mon May 17 13:37:03 PDT 2010
Revision: 5608
http://trac.macosforge.org/projects/calendarserver/changeset/5608
Author: cdaboo at apple.com
Date: 2010-05-17 13:37:00 -0700 (Mon, 17 May 2010)
Log Message:
-----------
Prevent request forwarding loops with partitioning.
Modified Paths:
--------------
CalendarServer/trunk/twistedcaldav/client/__init__.py
CalendarServer/trunk/twistedcaldav/client/reverseproxy.py
Added Paths:
-----------
CalendarServer/trunk/twistedcaldav/client/test/
CalendarServer/trunk/twistedcaldav/client/test/__init__.py
CalendarServer/trunk/twistedcaldav/client/test/test_reverseproxy.py
Modified: CalendarServer/trunk/twistedcaldav/client/__init__.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/client/__init__.py 2010-05-15 05:04:39 UTC (rev 5607)
+++ CalendarServer/trunk/twistedcaldav/client/__init__.py 2010-05-17 20:37:00 UTC (rev 5608)
@@ -14,3 +14,16 @@
# limitations under the License.
##
+from twext.web2.http_headers import DefaultHTTPHandler, tokenize, generateList, singleHeader
+
+DefaultHTTPHandler.updateParsers({
+ "x-forwarded-for": (tokenize, list),
+ "x-forwarded-host": (tokenize, list),
+ "x-forwarded-server": (tokenize, list),
+})
+DefaultHTTPHandler.updateGenerators({
+ "x-forwarded-for": (generateList, singleHeader),
+ "x-forwarded-host": (generateList, singleHeader),
+ "x-forwarded-server": (generateList, singleHeader),
+})
+
Modified: CalendarServer/trunk/twistedcaldav/client/reverseproxy.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/client/reverseproxy.py 2010-05-15 05:04:39 UTC (rev 5607)
+++ CalendarServer/trunk/twistedcaldav/client/reverseproxy.py 2010-05-17 20:37:00 UTC (rev 5608)
@@ -18,12 +18,11 @@
"ReverseProxyResource",
]
-import urllib
-
from zope.interface.declarations import implements
-from twext.web2 import iweb
+from twext.web2 import iweb, responsecode
from twext.web2.client.http import ClientRequest
+from twext.web2.http import StatusResponse, HTTPError
from twext.web2.resource import LeafResource
from twext.python.log import LoggingMixIn
@@ -47,6 +46,7 @@
self.poolID = poolID
self._args = args
self._kwargs = kwargs
+ self.allowMultiHop = False
def isCollection(self):
return True
@@ -65,13 +65,26 @@
"""
self.logger.info("%s %s %s" % (request.method, request.uri, "HTTP/%s.%s" % request.clientproto))
+
+ # Check for multi-hop
+ if not self.allowMultiHop:
+ x_server = request.headers.getHeader("x-forwarded-server")
+ if x_server:
+ for item in x_server:
+ if item == config.ServerHostName:
+ raise HTTPError(StatusResponse(responsecode.BAD_GATEWAY, "Too many x-forwarded-server hops"))
+
+
clientPool = getHTTPClientPool(self.poolID)
proxyRequest = ClientRequest(request.method, request.uri, request.headers, request.stream)
- # Need x-forwarded-(for|host) headers. First strip any existing ones out, then add ours
+ # Need x-forwarded-(for|host|server) headers. First strip any existing ones out, then add ours
proxyRequest.headers.removeHeader("x-forwarded-host")
proxyRequest.headers.removeHeader("x-forwarded-for")
- proxyRequest.headers.addRawHeader("x-forwarded-host", config.ServerHostName)
+ proxyRequest.headers.removeHeader("x-forwarded-server")
+ proxyRequest.headers.addRawHeader("x-forwarded-host", request.host)
proxyRequest.headers.addRawHeader("x-forwarded-for", request.remoteAddr.host)
+ proxyRequest.headers.addRawHeader("x-forwarded-server", config.ServerHostName)
return clientPool.submitRequest(proxyRequest)
+
Added: CalendarServer/trunk/twistedcaldav/client/test/__init__.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/client/test/__init__.py (rev 0)
+++ CalendarServer/trunk/twistedcaldav/client/test/__init__.py 2010-05-17 20:37:00 UTC (rev 5608)
@@ -0,0 +1,19 @@
+##
+# Copyright (c) 2010 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+"""
+Tests for the twistedcaldav.client module.
+"""
Added: CalendarServer/trunk/twistedcaldav/client/test/test_reverseproxy.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/client/test/test_reverseproxy.py (rev 0)
+++ CalendarServer/trunk/twistedcaldav/client/test/test_reverseproxy.py 2010-05-17 20:37:00 UTC (rev 5608)
@@ -0,0 +1,75 @@
+##
+# Copyright (c) 2010 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from twext.web2.client.http import ClientRequest
+from twext.web2.http import HTTPError
+from twext.web2.test.test_server import SimpleRequest
+from twistedcaldav.client.pool import _clientPools
+from twistedcaldav.client.reverseproxy import ReverseProxyResource
+from twistedcaldav.config import config
+import twistedcaldav.test.util
+
+class ReverseProxyNoLoop (twistedcaldav.test.util.TestCase):
+ """
+ Prevent loops in reverse proxy
+ """
+
+ def setUp(self):
+
+ class DummyPool(object):
+
+ def submitRequest(self, request):
+ return request
+
+ _clientPools["pool"] = DummyPool()
+
+ super(ReverseProxyNoLoop, self).setUp()
+
+ def test_No_Header(self):
+ proxy = ReverseProxyResource("pool")
+ request = SimpleRequest(proxy, "GET", "/")
+ self.assertIsInstance(proxy.renderHTTP(request), ClientRequest)
+
+ def test_Header_Other_Server(self):
+ proxy = ReverseProxyResource("pool")
+ request = SimpleRequest(proxy, "GET", "/")
+ request.headers.addRawHeader("x-forwarded-server", "foobar.example.com")
+ self.assertIsInstance(proxy.renderHTTP(request), ClientRequest)
+
+ def test_Header_Other_Servers(self):
+ proxy = ReverseProxyResource("pool")
+ request = SimpleRequest(proxy, "GET", "/")
+ request.headers.setHeader("x-forwarded-server", ("foobar.example.com", "bar.example.com",))
+ self.assertIsInstance(proxy.renderHTTP(request), ClientRequest)
+
+ def test_Header_Our_Server(self):
+ proxy = ReverseProxyResource("pool")
+ request = SimpleRequest(proxy, "GET", "/")
+ request.headers.addRawHeader("x-forwarded-server", config.ServerHostName)
+ self.assertRaises(HTTPError, proxy.renderHTTP, request)
+
+ def test_Header_Our_Server_Moxied(self):
+ proxy = ReverseProxyResource("pool")
+ request = SimpleRequest(proxy, "GET", "/")
+ request.headers.setHeader("x-forwarded-server", ("foobar.example.com", "bar.example.com", config.ServerHostName,))
+ self.assertRaises(HTTPError, proxy.renderHTTP, request)
+
+ def test_Header_Our_Server_Allowed(self):
+ proxy = ReverseProxyResource("pool")
+ proxy.allowMultiHop = True
+ request = SimpleRequest(proxy, "GET", "/")
+ request.headers.addRawHeader("x-forwarded-server", config.ServerHostName)
+ self.assertIsInstance(proxy.renderHTTP(request), ClientRequest)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20100517/07909cd8/attachment.html>
More information about the calendarserver-changes
mailing list