~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/chroot.py

  • Committer: Vincent Ladeuil
  • Date: 2010-06-18 15:36:27 UTC
  • mto: (5247.4.16 sftp-leaks)
  • mto: This revision was merged to the branch mainline in revision 5396.
  • Revision ID: v.ladeuil+lp@free.fr-20100618153627-2ceniy5w6f3zsmhw
Fix the last remaining failures.

* bzrlib/tests/test_server.py:
(TestingSmartServer.serve): Run the hooks.
(SmartTCPServer_for_testing.stop_server): Don't forget the chroot
server.

* bzrlib/tests/per_branch/test_push.py:
(EmptyPushSmartEffortTests.setUp): Fix the issubclass check, the
smart test server don't ihnerit directly from
server.SmartTCPServer anymore.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006 Canonical Ltd
 
1
# Copyright (C) 2006-2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""Implementation of Transport that prevents access to locations above a set
18
18
root.
19
19
"""
20
20
 
21
 
from bzrlib import errors, urlutils
22
 
from bzrlib.transport.decorator import TransportDecorator, DecoratorServer
23
 
 
24
 
 
25
 
class ChrootTransportDecorator(TransportDecorator):
26
 
    """A decorator that can convert any transport to be chrooted.
27
 
 
28
 
    This is requested via the 'chrooted+' prefix to get_transport().
29
 
    """
30
 
 
31
 
    def __init__(self, url, _decorated=None, chroot=None):
32
 
        super(ChrootTransportDecorator, self).__init__(url,
33
 
                _decorated=_decorated)
34
 
        if chroot is None:
35
 
            self.chroot_url = self._decorated.base
36
 
        else:
37
 
            self.chroot_url = chroot
38
 
 
39
 
    @classmethod
40
 
    def _get_url_prefix(self):
41
 
        """Chroot transport decorators are invoked via 'chroot+'"""
42
 
        return 'chroot+'
43
 
 
44
 
    def _ensure_relpath_is_child(self, relpath):
45
 
        abspath = self.abspath(relpath)
46
 
        chroot_base = self._get_url_prefix() + self.chroot_url
47
 
        real_relpath = urlutils.relative_url(chroot_base, abspath)
48
 
        if real_relpath == '..' or real_relpath.startswith('../'):
49
 
            raise errors.PathNotChild(relpath, self.chroot_url)
50
 
 
51
 
    # decorated methods
52
 
    def append_file(self, relpath, f, mode=None):
53
 
        self._ensure_relpath_is_child(relpath)
54
 
        return TransportDecorator.append_file(self, relpath, f, mode=mode)
55
 
 
56
 
    def append_bytes(self, relpath, bytes, mode=None):
57
 
        self._ensure_relpath_is_child(relpath)
58
 
        return TransportDecorator.append_bytes(self, relpath, bytes, mode=mode)
59
 
 
60
 
    def clone(self, offset=None):
61
 
        self._ensure_relpath_is_child(offset)
62
 
        return TransportDecorator.clone(self, offset)
63
 
 
64
 
    def delete(self, relpath):
65
 
        self._ensure_relpath_is_child(relpath)
66
 
        return TransportDecorator.delete(self, relpath)
67
 
 
68
 
    def delete_tree(self, relpath):
69
 
        self._ensure_relpath_is_child(relpath)
70
 
        return TransportDecorator.delete_tree(self, relpath)
71
 
 
72
 
    def get(self, relpath):
73
 
        self._ensure_relpath_is_child(relpath)
74
 
        return TransportDecorator.get(self, relpath)
75
 
 
76
 
    def get_bytes(self, relpath):
77
 
        self._ensure_relpath_is_child(relpath)
78
 
        return TransportDecorator.get_bytes(self, relpath)
79
 
 
80
 
    def has(self, relpath):
81
 
        self._ensure_relpath_is_child(relpath)
82
 
        return TransportDecorator.has(self, relpath)
83
 
 
84
 
    def list_dir(self, relpath):
85
 
        self._ensure_relpath_is_child(relpath)
86
 
        return TransportDecorator.list_dir(self, relpath)
87
 
 
88
 
    def lock_read(self, relpath):
89
 
        self._ensure_relpath_is_child(relpath)
90
 
        return TransportDecorator.lock_read(self, relpath)
91
 
 
92
 
    def lock_write(self, relpath):
93
 
        self._ensure_relpath_is_child(relpath)
94
 
        return TransportDecorator.lock_write(self, relpath)
95
 
 
96
 
    def mkdir(self, relpath, mode=None):
97
 
        self._ensure_relpath_is_child(relpath)
98
 
        return TransportDecorator.mkdir(self, relpath, mode=mode)
99
 
 
100
 
    def put_bytes(self, relpath, bytes, mode=None):
101
 
        self._ensure_relpath_is_child(relpath)
102
 
        return TransportDecorator.put_bytes(self, relpath, bytes, mode=mode)
103
 
 
104
 
    def put_file(self, relpath, f, mode=None):
105
 
        self._ensure_relpath_is_child(relpath)
106
 
        return TransportDecorator.put_file(self, relpath, f, mode=mode)
107
 
 
108
 
    def rename(self, rel_from, rel_to):
109
 
        self._ensure_relpath_is_child(rel_from)
110
 
        self._ensure_relpath_is_child(rel_to)
111
 
        return TransportDecorator.rename(self, rel_from, rel_to)
112
 
 
113
 
    def rmdir(self, relpath):
114
 
        self._ensure_relpath_is_child(relpath)
115
 
        return TransportDecorator.rmdir(self, relpath)
116
 
 
117
 
    def stat(self, relpath):
118
 
        self._ensure_relpath_is_child(relpath)
119
 
        return TransportDecorator.stat(self, relpath)
120
 
 
121
 
 
122
 
class ChrootServer(DecoratorServer):
123
 
    """Server for the ReadonlyTransportDecorator for testing with."""
124
 
 
125
 
    def get_decorator_class(self):
126
 
        return ChrootTransportDecorator
 
21
from bzrlib.transport import (
 
22
    pathfilter,
 
23
    register_transport,
 
24
    )
 
25
 
 
26
 
 
27
class ChrootServer(pathfilter.PathFilteringServer):
 
28
    """User space 'chroot' facility.
 
29
 
 
30
    The server's get_url returns the url for a chroot transport mapped to the
 
31
    backing transport. The url is of the form chroot-xxx:/// so parent
 
32
    directories of the backing transport are not visible. The chroot url will
 
33
    not allow '..' sequences to result in requests to the chroot affecting
 
34
    directories outside the backing transport.
 
35
 
 
36
    PathFilteringServer does all the path sanitation needed to enforce a
 
37
    chroot, so this is a simple subclass of PathFilteringServer that ignores
 
38
    filter_func.
 
39
    """
 
40
 
 
41
    def __init__(self, backing_transport):
 
42
        pathfilter.PathFilteringServer.__init__(self, backing_transport, None)
 
43
 
 
44
    def _factory(self, url):
 
45
        return ChrootTransport(self, url)
 
46
 
 
47
    def start_server(self):
 
48
        self.scheme = 'chroot-%d:///' % id(self)
 
49
        register_transport(self.scheme, self._factory)
 
50
 
 
51
 
 
52
class ChrootTransport(pathfilter.PathFilteringTransport):
 
53
    """A ChrootTransport.
 
54
 
 
55
    Please see ChrootServer for details.
 
56
    """
 
57
 
 
58
    def _filter(self, relpath):
 
59
        # A simplified version of PathFilteringTransport's _filter that omits
 
60
        # the call to self.server.filter_func.
 
61
        return self._relpath_from_server_root(relpath)
127
62
 
128
63
 
129
64
def get_test_permutations():
130
65
    """Return the permutations to be used in testing."""
131
 
    return [(ChrootTransportDecorator, ChrootServer),
132
 
            ]
 
66
    from bzrlib.tests import test_server
 
67
    return [(ChrootTransport, test_server.TestingChrootServer)]