~ubuntu-branches/ubuntu/natty/moin/natty-updates

« back to all changes in this revision

Viewing changes to MoinMoin/security/_tests/test_security.py

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Smedegaard
  • Date: 2008-06-22 21:17:13 UTC
  • mfrom: (0.9.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080622211713-fpo2zrq3s5dfecxg
Tags: 1.7.0-3
Simplify /etc/moin/wikilist format: "USER URL" (drop unneeded middle
CONFIG_DIR that was wrongly advertised as DATA_DIR).  Make
moin-mass-migrate handle both formats and warn about deprecation of
the old one.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: iso-8859-1 -*-
 
2
"""
 
3
    MoinMoin - MoinMoin.security Tests
 
4
 
 
5
    TODO: when refactoring this, do not use "iter" (is a builtin)
 
6
 
 
7
    @copyright: 2003-2004 by Juergen Hermann <jh@web.de>,
 
8
                2007 by MoinMoin:ReimarBauer,
 
9
                2007 by MoinMoin:ThomasWaldmann
 
10
    @license: GNU GPL, see COPYING for details.
 
11
"""
 
12
 
 
13
import py
 
14
 
 
15
from MoinMoin import security
 
16
acliter = security.ACLStringIterator
 
17
AccessControlList = security.AccessControlList
 
18
 
 
19
from MoinMoin.PageEditor import PageEditor
 
20
from MoinMoin.user import User
 
21
 
 
22
from MoinMoin._tests import become_trusted, create_page, nuke_page
 
23
 
 
24
class TestACLStringIterator(object):
 
25
 
 
26
    def setup_method(self, method):
 
27
        self.config = self.TestConfig(defaults=['acl_rights_valid', 'acl_rights_before'])
 
28
    def teardown_method(self, method):
 
29
        del self.config
 
30
 
 
31
    def testEmpty(self):
 
32
        """ security: empty acl string raise StopIteration """
 
33
        iter = acliter(self.request.cfg.acl_rights_valid, '')
 
34
        py.test.raises(StopIteration, iter.next)
 
35
 
 
36
    def testWhiteSpace(self):
 
37
        """ security: white space acl string raise StopIteration """
 
38
        iter = acliter(self.request.cfg.acl_rights_valid, '       ')
 
39
        py.test.raises(StopIteration, iter.next)
 
40
 
 
41
    def testDefault(self):
 
42
        """ security: default meta acl """
 
43
        iter = acliter(self.request.cfg.acl_rights_valid, 'Default Default')
 
44
        for mod, entries, rights in iter:
 
45
            assert entries == ['Default']
 
46
            assert rights == []
 
47
 
 
48
    def testEmptyRights(self):
 
49
        """ security: empty rights """
 
50
        iter = acliter(self.request.cfg.acl_rights_valid, 'WikiName:')
 
51
        mod, entries, rights = iter.next()
 
52
        assert entries == ['WikiName']
 
53
        assert rights == []
 
54
 
 
55
    def testSingleWikiNameSingleWrite(self):
 
56
        """ security: single wiki name, single right """
 
57
        iter = acliter(self.request.cfg.acl_rights_valid, 'WikiName:read')
 
58
        mod, entries, rights = iter.next()
 
59
        assert entries == ['WikiName']
 
60
        assert rights == ['read']
 
61
 
 
62
    def testMultipleWikiNameAndRights(self):
 
63
        """ security: multiple wiki names and rights """
 
64
        iter = acliter(self.request.cfg.acl_rights_valid, 'UserOne,UserTwo:read,write')
 
65
        mod, entries, rights = iter.next()
 
66
        assert entries == ['UserOne', 'UserTwo']
 
67
        assert rights == ['read', 'write']
 
68
 
 
69
    def testMultipleWikiNameAndRightsSpaces(self):
 
70
        """ security: multiple names with spaces """
 
71
        iter = acliter(self.request.cfg.acl_rights_valid, 'user one,user two:read')
 
72
        mod, entries, rights = iter.next()
 
73
        assert entries == ['user one', 'user two']
 
74
        assert rights == ['read']
 
75
 
 
76
    def testMultipleEntries(self):
 
77
        """ security: multiple entries """
 
78
        iter = acliter(self.request.cfg.acl_rights_valid, 'UserOne:read,write UserTwo:read All:')
 
79
        mod, entries, rights = iter.next()
 
80
        assert entries == ['UserOne']
 
81
        assert rights == ['read', 'write']
 
82
        mod, entries, rights = iter.next()
 
83
        assert entries == ['UserTwo']
 
84
        assert rights == ['read']
 
85
        mod, entries, rights = iter.next()
 
86
        assert entries == ['All']
 
87
        assert rights == []
 
88
 
 
89
    def testNameWithSpaces(self):
 
90
        """ security: single name with spaces """
 
91
        iter = acliter(self.request.cfg.acl_rights_valid, 'user one:read')
 
92
        mod, entries, rights = iter.next()
 
93
        assert entries == ['user one']
 
94
        assert rights == ['read']
 
95
 
 
96
    def testMultipleEntriesWithSpaces(self):
 
97
        """ security: multiple entries with spaces """
 
98
        iter = acliter(self.request.cfg.acl_rights_valid, 'user one:read,write user two:read')
 
99
        mod, entries, rights = iter.next()
 
100
        assert entries == ['user one']
 
101
        assert rights == ['read', 'write']
 
102
        mod, entries, rights = iter.next()
 
103
        assert entries == ['user two']
 
104
        assert rights == ['read']
 
105
 
 
106
    def testMixedNames(self):
 
107
        """ security: mixed wiki names and names with spaces """
 
108
        iter = acliter(self.request.cfg.acl_rights_valid, 'UserOne,user two:read,write user three,UserFour:read')
 
109
        mod, entries, rights = iter.next()
 
110
        assert entries == ['UserOne', 'user two']
 
111
        assert rights == ['read', 'write']
 
112
        mod, entries, rights = iter.next()
 
113
        assert entries == ['user three', 'UserFour']
 
114
        assert rights == ['read']
 
115
 
 
116
    def testModifier(self):
 
117
        """ security: acl modifiers """
 
118
        iter = acliter(self.request.cfg.acl_rights_valid, '+UserOne:read -UserTwo:')
 
119
        mod, entries, rights = iter.next()
 
120
        assert mod == '+'
 
121
        assert entries == ['UserOne']
 
122
        assert rights == ['read']
 
123
        mod, entries, rights = iter.next()
 
124
        assert mod == '-'
 
125
        assert entries == ['UserTwo']
 
126
        assert rights == []
 
127
 
 
128
    def testIgnoreInvalidACL(self):
 
129
        """ security: ignore invalid acl
 
130
 
 
131
        The last part of this acl can not be parsed. If it ends with :
 
132
        then it will be parsed as one name with spaces.
 
133
        """
 
134
        iter = acliter(self.request.cfg.acl_rights_valid, 'UserOne:read user two is ignored')
 
135
        mod, entries, rights = iter.next()
 
136
        assert entries == ['UserOne']
 
137
        assert rights == ['read']
 
138
        py.test.raises(StopIteration, iter.next)
 
139
 
 
140
    def testEmptyNamesWithRight(self):
 
141
        """ security: empty names with rights
 
142
 
 
143
        The documents does not talk about this case, may() should ignore
 
144
        the rights because there is no entry.
 
145
        """
 
146
        iter = acliter(self.request.cfg.acl_rights_valid, 'UserOne:read :read All:')
 
147
        mod, entries, rights = iter.next()
 
148
        assert entries == ['UserOne']
 
149
        assert rights == ['read']
 
150
        mod, entries, rights = iter.next()
 
151
        assert entries == []
 
152
        assert rights == ['read']
 
153
        mod, entries, rights = iter.next()
 
154
        assert entries == ['All']
 
155
        assert rights == []
 
156
 
 
157
    def testIgnodeInvalidRights(self):
 
158
        """ security: ignore rights not in acl_rights_valid """
 
159
        iter = acliter(self.request.cfg.acl_rights_valid, 'UserOne:read,sing,write,drink,sleep')
 
160
        mod, entries, rights = iter.next()
 
161
        assert rights == ['read', 'write']
 
162
 
 
163
    def testBadGuy(self):
 
164
        """ security: bad guy may not allowed anything
 
165
 
 
166
        This test was failing on the apply acl rights test.
 
167
        """
 
168
        iter = acliter(self.request.cfg.acl_rights_valid, 'UserOne:read,write BadGuy: All:read')
 
169
        mod, entries, rights = iter.next()
 
170
        mod, entries, rights = iter.next()
 
171
        assert entries == ['BadGuy']
 
172
        assert rights == []
 
173
 
 
174
    def testAllowExtraWhitespace(self):
 
175
        """ security: allow extra white space between entries """
 
176
        iter = acliter(self.request.cfg.acl_rights_valid, 'UserOne,user two:read,write   user three,UserFour:read  All:')
 
177
        mod, entries, rights = iter.next()
 
178
        assert  entries == ['UserOne', 'user two']
 
179
        assert rights == ['read', 'write']
 
180
        mod, entries, rights = iter.next()
 
181
        assert entries == ['user three', 'UserFour']
 
182
        assert rights == ['read']
 
183
        mod, entries, rights = iter.next()
 
184
        assert entries == ['All']
 
185
        assert rights == []
 
186
 
 
187
 
 
188
class TestAcl(object):
 
189
    """ security: testing access control list
 
190
 
 
191
    TO DO: test unknown user?
 
192
    """
 
193
    def setup_method(self, method):
 
194
        # Backup user
 
195
        self.config = self.TestConfig(defaults=['acl_rights_valid', 'acl_rights_before'])
 
196
        self.savedUser = self.request.user.name
 
197
 
 
198
    def teardown_method(self, method):
 
199
        # Restore user
 
200
        self.request.user.name = self.savedUser
 
201
        del self.config
 
202
 
 
203
    def testApplyACLByUser(self):
 
204
        """ security: applying acl by user name"""
 
205
        # This acl string...
 
206
        acl_rights = [
 
207
            "Admin1,Admin2:read,write,delete,revert,admin  "
 
208
            "Admin3:read,write,admin  "
 
209
            "JoeDoe:read,write  "
 
210
            "name with spaces,another one:read,write  "
 
211
            "CamelCase,extended name:read,write  "
 
212
            "BadGuy:  "
 
213
            "All:read  "
 
214
            ]
 
215
        acl = security.AccessControlList(self.request.cfg, acl_rights)
 
216
 
 
217
        # Should apply these rights:
 
218
        users = (
 
219
            # user,                 rights
 
220
            # CamelCase names
 
221
            ('Admin1', ('read', 'write', 'admin', 'revert', 'delete')),
 
222
            ('Admin2', ('read', 'write', 'admin', 'revert', 'delete')),
 
223
            ('Admin3', ('read', 'write', 'admin')),
 
224
            ('JoeDoe', ('read', 'write')),
 
225
            ('SomeGuy', ('read', )),
 
226
            # Extended names or mix of extended and CamelCase
 
227
            ('name with spaces', ('read', 'write', )),
 
228
            ('another one', ('read', 'write', )),
 
229
            ('CamelCase', ('read', 'write', )),
 
230
            ('extended name', ('read', 'write', )),
 
231
            # Blocking bad guys
 
232
            ('BadGuy', ()),
 
233
            # All other users - every one not mentioned in the acl lines
 
234
            ('All', ('read', )),
 
235
            ('Anonymous', ('read', )),
 
236
            )
 
237
 
 
238
        # Check rights
 
239
        for user, may in users:
 
240
            mayNot = [right for right in self.request.cfg.acl_rights_valid
 
241
                      if right not in may]
 
242
            # User should have these rights...
 
243
            for right in may:
 
244
                assert acl.may(self.request, user, right)
 
245
            # But NOT these:
 
246
            for right in mayNot:
 
247
                assert not acl.may(self.request, user, right)
 
248
 
 
249
 
 
250
class TestPageAcls(object):
 
251
    """ security: real-life access control list on pages testing
 
252
    """
 
253
    acls_before = u"WikiAdmin:admin,read,write,delete,revert"
 
254
    acls_default = u"All:read,write"
 
255
    acls_after = u"All:read"
 
256
    mainpage_name = u'AclTestMainPage'
 
257
    subpage_name = u'AclTestMainPage/SubPage'
 
258
    pages = [
 
259
        # pagename, content
 
260
        (mainpage_name, u"#acl JoeDoe: JaneDoe:read,write\nFoo!"),
 
261
        (subpage_name, u"FooFoo!"),
 
262
    ]
 
263
 
 
264
    def setup_class(self):
 
265
        self.config = self.TestConfig(
 
266
            acl_rights_before=self.acls_before,
 
267
            acl_rights_default=self.acls_default,
 
268
            acl_rights_after=self.acls_after,
 
269
            acl_hierarchic=False,
 
270
            defaults=['acl_rights_valid'])
 
271
        # TestConfig is crap, it does some wild hack and does not inherit from DefaultConfig
 
272
        # nor call DefaultConfig's __init__() to do post processing, thus we do it here for now:
 
273
        cfg = self.request.cfg
 
274
        cfg.cache.acl_rights_before = AccessControlList(cfg, [cfg.acl_rights_before])
 
275
        cfg.cache.acl_rights_default = AccessControlList(cfg, [cfg.acl_rights_default])
 
276
        cfg.cache.acl_rights_after = AccessControlList(cfg, [cfg.acl_rights_after])
 
277
 
 
278
        # Backup user
 
279
        self.savedUser = self.request.user.name
 
280
        self.request.user = User(self.request, auth_username=u'WikiAdmin')
 
281
        self.request.user.valid = True
 
282
 
 
283
        for page_name, page_content in self.pages:
 
284
            create_page(self.request, page_name, page_content)
 
285
 
 
286
    def teardown_class(self):
 
287
        del self.config
 
288
        cfg = self.request.cfg
 
289
        cfg.cache.acl_rights_before = AccessControlList(cfg, [cfg.acl_rights_before])
 
290
        cfg.cache.acl_rights_default = AccessControlList(cfg, [cfg.acl_rights_default])
 
291
        cfg.cache.acl_rights_after = AccessControlList(cfg, [cfg.acl_rights_after])
 
292
 
 
293
        # Restore user
 
294
        self.request.user.name = self.savedUser
 
295
 
 
296
        for page_name, dummy in self.pages:
 
297
            nuke_page(self.request, page_name)
 
298
 
 
299
    def testPageACLs(self):
 
300
        """ security: test page acls """
 
301
        tests = [
 
302
            # hierarchic, pagename, username, expected_rights
 
303
            (False, self.mainpage_name, u'WikiAdmin', ['read', 'write', 'admin', 'revert', 'delete']),
 
304
            (True,  self.mainpage_name, u'WikiAdmin', ['read', 'write', 'admin', 'revert', 'delete']),
 
305
            (False, self.mainpage_name, u'AnyUser', ['read']), # by after acl
 
306
            (True,  self.mainpage_name, u'AnyUser', ['read']), # by after acl
 
307
            (False, self.mainpage_name, u'JaneDoe', ['read', 'write']), # by page acl
 
308
            (True,  self.mainpage_name, u'JaneDoe', ['read', 'write']), # by page acl
 
309
            (False, self.mainpage_name, u'JoeDoe', []), # by page acl
 
310
            (True,  self.mainpage_name, u'JoeDoe', []), # by page acl
 
311
            (False, self.subpage_name, u'WikiAdmin', ['read', 'write', 'admin', 'revert', 'delete']),
 
312
            (True,  self.subpage_name, u'WikiAdmin', ['read', 'write', 'admin', 'revert', 'delete']),
 
313
            (False, self.subpage_name, u'AnyUser', ['read', 'write']), # by default acl
 
314
            (True,  self.subpage_name, u'AnyUser', ['read']), # by after acl
 
315
            (False, self.subpage_name, u'JoeDoe', ['read', 'write']), # by default acl
 
316
            (True,  self.subpage_name, u'JoeDoe', []), # by inherited acl from main page
 
317
            (False, self.subpage_name, u'JaneDoe', ['read', 'write']), # by default acl
 
318
            (True,  self.subpage_name, u'JaneDoe', ['read', 'write']), # by inherited acl from main page
 
319
        ]
 
320
 
 
321
        for hierarchic, pagename, username, may in tests:
 
322
            self.request.cfg.acl_hierarchic = hierarchic
 
323
            u = User(self.request, auth_username=username)
 
324
            u.valid = True
 
325
 
 
326
            # User should have these rights...
 
327
            for right in may:
 
328
                can_access = u.may.__getattr__(right)(pagename)
 
329
                if can_access:
 
330
                    print "page %s: %s test if %s may %s (success)" % (
 
331
                        pagename, ['normal', 'hierarchic'][hierarchic], username, right)
 
332
                else:
 
333
                    print "page %s: %s test if %s may %s (failure)" % (
 
334
                        pagename, ['normal', 'hierarchic'][hierarchic], username, right)
 
335
                assert can_access
 
336
 
 
337
            # User should NOT have these rights:
 
338
            mayNot = [right for right in self.request.cfg.acl_rights_valid
 
339
                      if right not in may]
 
340
            for right in mayNot:
 
341
                can_access = u.may.__getattr__(right)(pagename)
 
342
                if can_access:
 
343
                    print "page %s: %s test if %s may not %s (failure)" % (
 
344
                        pagename, ['normal', 'hierarchic'][hierarchic], username, right)
 
345
                else:
 
346
                    print "page %s: %s test if %s may not %s (success)" % (
 
347
                        pagename, ['normal', 'hierarchic'][hierarchic], username, right)
 
348
                assert not can_access
 
349
 
 
350
coverage_modules = ['MoinMoin.security']