comparison roundup/security.py @ 4437:261c9f913ff7

- Add explicit "Search" permissions, see Security Fix below. - Security Fix: Add a check for search-permissions: now we allow searching for properties only if the property is readable without a check method or if an explicit search permission (see above unter "Features) is given for the property. This fixes cases where a user doesn't have access to a property but can deduce the content by crafting a clever search, group or sort query. see doc/upgrading.txt for how to fix your trackers!
author Ralf Schlatterbeck <schlatterbeck@users.sourceforge.net>
date Tue, 19 Oct 2010 15:29:05 +0000
parents 966592263fb8
children 222efa59ee6c
comparison
equal deleted inserted replaced
4436:528ace81fd16 4437:261c9f913ff7
52 return 0 52 return 0
53 53
54 # we have a winner 54 # we have a winner
55 return 1 55 return 1
56 56
57 def searchable(self, db, permission, classname, property):
58 """ A Permission is searchable for the given permission if it
59 doesn't include a check method and otherwise matches the
60 given parameters.
61 """
62 if permission != self.name:
63 return 0
64
65 # are we checking the correct class
66 if self.klass != classname:
67 return 0
68
69 # what about property?
70 if not self._properties_dict[property]:
71 return 0
72
73 if self.check:
74 return 0
75
76 return 1
77
78
57 def __repr__(self): 79 def __repr__(self):
58 return '<Permission 0x%x %r,%r,%r,%r>'%(id(self), self.name, 80 return '<Permission 0x%x %r,%r,%r,%r>'%(id(self), self.name,
59 self.klass, self.properties, self.check) 81 self.klass, self.properties, self.check)
60 82
61 def __cmp__(self, other): 83 def __cmp__(self, other):
173 if perm.test(self.db, permission, classname, property, 195 if perm.test(self.db, permission, classname, property,
174 userid, itemid): 196 userid, itemid):
175 return 1 197 return 1
176 return 0 198 return 0
177 199
200 def roleHasSearchPermission(self, rolename, classname, property):
201 """ for each of the user's Roles, check the permissions
202 """
203 for perm in self.role[rolename].permissions:
204 # permission match?
205 for p in 'View', 'Search':
206 if perm.searchable(self.db, p, classname, property):
207 return 1
208 return 0
209
210 def hasSearchPermission(self, userid, classname, property):
211 '''Look through all the Roles, and hence Permissions, and
212 see if "permission" exists given the constraints of
213 classname and property.
214
215 A search permission is granted if we find a 'View' or
216 'Search' permission for the user which does *not* include
217 a check function. If such a permission is found, the user may
218 search for the given property in the given class.
219
220 Note that classname *and* property are mandatory arguments.
221
222 Contrary to hasPermission, the search will *not* match if
223 there are additional constraints (namely a search function)
224 on a Permission found.
225
226 Concerning property, the Permission matched must have
227 either no properties listed or the property must appear in
228 the list.
229 '''
230 for rolename in self.db.user.get_roles(userid):
231 if not rolename or not self.role.has_key(rolename):
232 continue
233 # for each of the user's Roles, check the permissions
234 if self.roleHasSearchPermission (rolename, classname, property):
235 return 1
236 return 0
237
178 def addPermission(self, **propspec): 238 def addPermission(self, **propspec):
179 ''' Create a new Permission with the properties defined in 239 ''' Create a new Permission with the properties defined in
180 'propspec'. See the Permission class for the possible 240 'propspec'. See the Permission class for the possible
181 keyword args. 241 keyword args.
182 ''' 242 '''
206 permission = self.getPermission(permission, classname, 266 permission = self.getPermission(permission, classname,
207 properties, check) 267 properties, check)
208 role = self.role[rolename.lower()] 268 role = self.role[rolename.lower()]
209 role.permissions.append(permission) 269 role.permissions.append(permission)
210 270
271 # Convenience methods for removing non-allowed properties from a
272 # filterspec or sort/group list
273
274 def filterFilterspec(self, userid, classname, filterspec):
275 """ Return a filterspec that has all non-allowed properties removed.
276 """
277 return dict ([(k, v) for k, v in filterspec.iteritems()
278 if self.hasSearchPermission(userid,classname,k)])
279
280 def filterSortspec(self, userid, classname, sort):
281 """ Return a sort- or group-list that has all non-allowed properties
282 removed.
283 """
284 if isinstance(sort, tuple) and sort[0] in '+-':
285 sort = [sort]
286 return [(d, p) for d, p in sort
287 if self.hasSearchPermission(userid,classname,p)]
288
211 # vim: set filetype=python sts=4 sw=4 et si : 289 # vim: set filetype=python sts=4 sw=4 et si :

Roundup Issue Tracker: http://roundup-tracker.org/