Rev 4762: (andrew) Fix jail break errors in bzr+http servers. (#348308) in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Thu Oct 22 02:07:27 BST 2009
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 4762 [merge]
revision-id: pqm at pqm.ubuntu.com-20091022010725-lzpmhctqph34xcol
parent: pqm at pqm.ubuntu.com-20091021163017-itbys2a178vt5605
parent: andrew.bennetts at canonical.com-20091021231524-w0uu60fgyb8s2zta
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Thu 2009-10-22 02:07:25 +0100
message:
(andrew) Fix jail break errors in bzr+http servers. (#348308)
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/smart/branch.py branch.py-20061124031907-mzh3pla28r83r97f-1
bzrlib/smart/protocol.py protocol.py-20061108035435-ot0lstk2590yqhzr-1
bzrlib/smart/request.py request.py-20061108095550-gunadhxmzkdjfeek-1
bzrlib/tests/test_wsgi.py test_wsgi.py-20061005091552-rz8pva0olkxv0sd8-1
bzrlib/transport/http/wsgi.py wsgi.py-20061005091552-rz8pva0olkxv0sd8-2
=== modified file 'NEWS'
--- a/NEWS 2009-10-21 14:32:16 +0000
+++ b/NEWS 2009-10-22 01:07:25 +0000
@@ -22,6 +22,9 @@
Bug Fixes
*********
+* ``bzr+http`` servers no longer give spurious jail break errors when
+ serving branches inside a shared repository. (Andrew Bennetts, #348308)
+
* TreeTransform.adjust_path updates the limbo paths of descendants of adjusted
files. (Aaron Bentley)
=== modified file 'bzrlib/smart/branch.py'
--- a/bzrlib/smart/branch.py 2009-07-27 04:32:56 +0000
+++ b/bzrlib/smart/branch.py 2009-10-21 06:05:49 +0000
@@ -105,9 +105,9 @@
class SmartServerBranchSetTagsBytes(SmartServerLockedBranchRequest):
- def __init__(self, backing_transport, root_client_path='/'):
+ def __init__(self, backing_transport, root_client_path='/', jail_root=None):
SmartServerLockedBranchRequest.__init__(
- self, backing_transport, root_client_path)
+ self, backing_transport, root_client_path, jail_root)
self.locked = False
def do_with_locked_branch(self, branch):
=== modified file 'bzrlib/smart/protocol.py'
--- a/bzrlib/smart/protocol.py 2009-09-11 06:07:05 +0000
+++ b/bzrlib/smart/protocol.py 2009-10-21 06:05:49 +0000
@@ -114,9 +114,11 @@
class SmartServerRequestProtocolOne(SmartProtocolBase):
"""Server-side encoding and decoding logic for smart version 1."""
- def __init__(self, backing_transport, write_func, root_client_path='/'):
+ def __init__(self, backing_transport, write_func, root_client_path='/',
+ jail_root=None):
self._backing_transport = backing_transport
self._root_client_path = root_client_path
+ self._jail_root = jail_root
self.unused_data = ''
self._finished = False
self.in_buffer = ''
@@ -144,7 +146,8 @@
req_args = _decode_tuple(first_line)
self.request = request.SmartServerRequestHandler(
self._backing_transport, commands=request.request_handlers,
- root_client_path=self._root_client_path)
+ root_client_path=self._root_client_path,
+ jail_root=self._jail_root)
self.request.args_received(req_args)
if self.request.finished_reading:
# trivial request
@@ -858,10 +861,10 @@
def build_server_protocol_three(backing_transport, write_func,
- root_client_path):
+ root_client_path, jail_root=None):
request_handler = request.SmartServerRequestHandler(
backing_transport, commands=request.request_handlers,
- root_client_path=root_client_path)
+ root_client_path=root_client_path, jail_root=jail_root)
responder = ProtocolThreeResponder(write_func)
message_handler = message.ConventionalRequestHandler(request_handler, responder)
return ProtocolThreeDecoder(message_handler)
=== modified file 'bzrlib/smart/request.py'
--- a/bzrlib/smart/request.py 2009-09-24 05:31:23 +0000
+++ b/bzrlib/smart/request.py 2009-10-21 06:05:49 +0000
@@ -86,7 +86,7 @@
# XXX: rename this class to BaseSmartServerRequestHandler ? A request
# *handler* is a different concept to the request.
- def __init__(self, backing_transport, root_client_path='/'):
+ def __init__(self, backing_transport, root_client_path='/', jail_root=None):
"""Constructor.
:param backing_transport: the base transport to be used when performing
@@ -96,8 +96,13 @@
from the client. Clients will not be able to refer to paths above
this root. If root_client_path is None, then no translation will
be performed on client paths. Default is '/'.
+ :param jail_root: if specified, the root of the BzrDir.open jail to use
+ instead of backing_transport.
"""
self._backing_transport = backing_transport
+ if jail_root is None:
+ jail_root = backing_transport
+ self._jail_root = jail_root
if root_client_path is not None:
if not root_client_path.startswith('/'):
root_client_path = '/' + root_client_path
@@ -155,7 +160,7 @@
return self.do_body(body_bytes)
def setup_jail(self):
- jail_info.transports = [self._backing_transport]
+ jail_info.transports = [self._jail_root]
def teardown_jail(self):
jail_info.transports = None
@@ -265,7 +270,8 @@
# TODO: Better way of representing the body for commands that take it,
# and allow it to be streamed into the server.
- def __init__(self, backing_transport, commands, root_client_path):
+ def __init__(self, backing_transport, commands, root_client_path,
+ jail_root):
"""Constructor.
:param backing_transport: a Transport to handle requests for.
@@ -275,6 +281,7 @@
self._backing_transport = backing_transport
self._root_client_path = root_client_path
self._commands = commands
+ self._jail_root = jail_root
self.response = None
self.finished_reading = False
self._command = None
@@ -335,7 +342,7 @@
except LookupError:
raise errors.UnknownSmartMethod(cmd)
self._command = command(
- self._backing_transport, self._root_client_path)
+ self._backing_transport, self._root_client_path, self._jail_root)
self._run_handler_code(self._command.execute, args, {})
def end_received(self):
=== modified file 'bzrlib/tests/test_wsgi.py'
--- a/bzrlib/tests/test_wsgi.py 2009-03-23 14:59:43 +0000
+++ b/bzrlib/tests/test_wsgi.py 2009-10-21 11:13:40 +0000
@@ -19,17 +19,12 @@
from cStringIO import StringIO
from bzrlib import tests
-from bzrlib.smart import protocol
+from bzrlib.smart import medium, message, protocol
from bzrlib.transport.http import wsgi
from bzrlib.transport import chroot, memory
-class TestWSGI(tests.TestCase):
-
- def setUp(self):
- tests.TestCase.setUp(self)
- self.status = None
- self.headers = None
+class WSGITestMixin(object):
def build_environ(self, updates=None):
"""Builds an environ dict with all fields required by PEP 333.
@@ -69,6 +64,14 @@
self.status = status
self.headers = headers
+
+class TestWSGI(tests.TestCase, WSGITestMixin):
+
+ def setUp(self):
+ tests.TestCase.setUp(self)
+ self.status = None
+ self.headers = None
+
def test_construct(self):
app = wsgi.SmartWSGIApp(FakeTransport())
self.assertIsInstance(
@@ -242,6 +245,51 @@
protocol.RESPONSE_VERSION_TWO + 'success\nok\x012\n', response)
+class TestWSGIJail(tests.TestCaseWithMemoryTransport, WSGITestMixin):
+
+ def make_hpss_wsgi_request(self, wsgi_relpath, *args):
+ write_buf = StringIO()
+ request_medium = medium.SmartSimplePipesClientMedium(
+ None, write_buf, 'fake:' + wsgi_relpath)
+ request_encoder = protocol.ProtocolThreeRequester(
+ request_medium.get_request())
+ request_encoder.call(*args)
+ write_buf.seek(0)
+ environ = self.build_environ({
+ 'REQUEST_METHOD': 'POST',
+ 'CONTENT_LENGTH': len(write_buf.getvalue()),
+ 'wsgi.input': write_buf,
+ 'bzrlib.relpath': wsgi_relpath,
+ })
+ return environ
+
+ def test_jail_root(self):
+ """The WSGI HPSS glue allows access to the whole WSGI backing
+ transport, regardless of which HTTP path the request was delivered
+ to.
+ """
+ # make a branch in a shared repo
+ self.make_repository('repo', shared=True)
+ branch = self.make_bzrdir('repo/branch').create_branch()
+ # serve the repo via bzr+http WSGI
+ wsgi_app = wsgi.SmartWSGIApp(self.get_transport())
+ # send a request to /repo/branch that will have to access /repo.
+ environ = self.make_hpss_wsgi_request(
+ '/repo/branch', 'BzrDir.open_branchV2', '.')
+ iterable = wsgi_app(environ, self.start_response)
+ response_bytes = self.read_response(iterable)
+ self.assertEqual('200 OK', self.status)
+ # expect a successful response, rather than a jail break error
+ from bzrlib.tests.test_smart_transport import LoggingMessageHandler
+ message_handler = LoggingMessageHandler()
+ decoder = protocol.ProtocolThreeDecoder(
+ message_handler, expect_version_marker=True)
+ decoder.accept_bytes(response_bytes)
+ self.assertTrue(
+ ('structure', ('branch', branch._format.network_name()))
+ in message_handler.event_log)
+
+
class FakeRequest(object):
def __init__(self, transport, write_func):
=== modified file 'bzrlib/transport/http/wsgi.py'
--- a/bzrlib/transport/http/wsgi.py 2009-03-23 14:59:43 +0000
+++ b/bzrlib/transport/http/wsgi.py 2009-10-21 06:05:49 +0000
@@ -176,6 +176,7 @@
def make_request(self, transport, write_func, request_bytes, rcp):
protocol_factory, unused_bytes = medium._get_protocol_factory_for_bytes(
request_bytes)
- server_protocol = protocol_factory(transport, write_func, rcp)
+ server_protocol = protocol_factory(
+ transport, write_func, rcp, self.backing_transport)
server_protocol.accept_bytes(unused_bytes)
return server_protocol
More information about the bazaar-commits
mailing list