AccessControl 7.6__cp315-cp315-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. AccessControl/AuthEncoding.py +48 -0
  2. AccessControl/ImplC.py +39 -0
  3. AccessControl/ImplPython.py +914 -0
  4. AccessControl/Implementation.py +111 -0
  5. AccessControl/Owned.py +30 -0
  6. AccessControl/Permission.py +179 -0
  7. AccessControl/PermissionMapping.py +165 -0
  8. AccessControl/PermissionRole.py +19 -0
  9. AccessControl/Permissions.py +65 -0
  10. AccessControl/Role.py +34 -0
  11. AccessControl/SecurityInfo.py +502 -0
  12. AccessControl/SecurityManagement.py +84 -0
  13. AccessControl/SecurityManager.py +30 -0
  14. AccessControl/SimpleObjectPolicies.py +151 -0
  15. AccessControl/SpecialUsers.py +25 -0
  16. AccessControl/User.py +54 -0
  17. AccessControl/ZopeGuards.py +712 -0
  18. AccessControl/ZopeSecurityPolicy.py +61 -0
  19. AccessControl/__init__.py +55 -0
  20. AccessControl/_compat.h +18 -0
  21. AccessControl/cAccessControl.c +2526 -0
  22. AccessControl/cAccessControl.cp315-win_amd64.pyd +0 -0
  23. AccessControl/class_init.py +94 -0
  24. AccessControl/configure.zcml +5 -0
  25. AccessControl/frozen.py +57 -0
  26. AccessControl/interfaces.py +390 -0
  27. AccessControl/logger_wrapper.py +8 -0
  28. AccessControl/meta.zcml +52 -0
  29. AccessControl/metaconfigure.py +61 -0
  30. AccessControl/owner.py +288 -0
  31. AccessControl/permissions.zcml +100 -0
  32. AccessControl/requestmethod.py +96 -0
  33. AccessControl/rolemanager.py +490 -0
  34. AccessControl/safe_formatter.py +86 -0
  35. AccessControl/security.py +203 -0
  36. AccessControl/tainted.py +195 -0
  37. AccessControl/tests/__init__.py +0 -0
  38. AccessControl/tests/actual_python.py +260 -0
  39. AccessControl/tests/mixed_module/__init__.py +9 -0
  40. AccessControl/tests/mixed_module/submodule/__init__.py +5 -0
  41. AccessControl/tests/private_module/__init__.py +5 -0
  42. AccessControl/tests/private_module/submodule/__init__.py +5 -0
  43. AccessControl/tests/public_module/__init__.py +11 -0
  44. AccessControl/tests/public_module/submodule/__init__.py +5 -0
  45. AccessControl/tests/testClassSecurityInfo.py +192 -0
  46. AccessControl/tests/testImplementation.py +65 -0
  47. AccessControl/tests/testModuleSecurity.py +335 -0
  48. AccessControl/tests/testPermissionMapping.py +12 -0
  49. AccessControl/tests/testPermissionRole.py +170 -0
  50. AccessControl/tests/testSecurityManager.py +264 -0
  51. AccessControl/tests/testZCML.py +489 -0
  52. AccessControl/tests/testZopeGuards.py +1086 -0
  53. AccessControl/tests/testZopeSecurityPolicy.py +799 -0
  54. AccessControl/tests/test_frozen.py +124 -0
  55. AccessControl/tests/test_owner.py +289 -0
  56. AccessControl/tests/test_requestmethod.py +138 -0
  57. AccessControl/tests/test_rolemanager.py +137 -0
  58. AccessControl/tests/test_safe_formatter.py +226 -0
  59. AccessControl/tests/test_safeiter.py +59 -0
  60. AccessControl/tests/test_tainted.py +320 -0
  61. AccessControl/tests/test_userfolder.py +198 -0
  62. AccessControl/tests/test_users.py +666 -0
  63. AccessControl/unauthorized.py +38 -0
  64. AccessControl/userfolder.py +432 -0
  65. AccessControl/users.py +502 -0
  66. accesscontrol-7.6.dist-info/METADATA +474 -0
  67. accesscontrol-7.6.dist-info/RECORD +71 -0
  68. accesscontrol-7.6.dist-info/WHEEL +5 -0
  69. accesscontrol-7.6.dist-info/entry_points.txt +2 -0
  70. accesscontrol-7.6.dist-info/licenses/LICENSE.txt +44 -0
  71. accesscontrol-7.6.dist-info/top_level.txt +1 -0
@@ -0,0 +1,502 @@
1
+ ##############################################################################
2
+ #
3
+ # Copyright (c) 2002 Zope Foundation and Contributors.
4
+ #
5
+ # This software is subject to the provisions of the Zope Public License,
6
+ # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7
+ # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8
+ # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9
+ # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10
+ # FOR A PARTICULAR PURPOSE
11
+ #
12
+ ##############################################################################
13
+ """SecurityInfo objects and access control constants.
14
+
15
+ SecurityInfo objects are used in class definitions to allow
16
+ a declarative style of associating access control information
17
+ with class attributes.
18
+
19
+ More information on using SecurityInfo and guide to Zope security
20
+ for developers can be found in the dev.zope.org "Declarative Security"
21
+ project:
22
+
23
+ http://dev.zope.org/Wikis/DevSite/Projects/DeclarativeSecurity
24
+
25
+ While SecurityInfo objects largely remove the need for Python
26
+ programmers to care about the underlying implementation, there
27
+ are several constants defined that should be used by code that
28
+ must set __roles__ attributes directly. (the constants are also
29
+ accessible from the AccessControl namespace). The defined access
30
+ control constants and their meanings are:
31
+
32
+ ACCESS_PUBLIC: accessible from restricted code and possibly
33
+ through the web (if object has a docstring)
34
+
35
+ ACCESS_PRIVATE: accessible only from python code
36
+
37
+ ACCESS_NONE: no access
38
+
39
+ """
40
+
41
+ import sys
42
+ from logging import getLogger
43
+
44
+ from Acquisition import Implicit
45
+ from Persistence import Persistent
46
+
47
+ from AccessControl import frozen
48
+ from AccessControl.class_init import InitializeClass
49
+ from AccessControl.ImplPython import _what_not_even_god_should_do
50
+
51
+
52
+ # always patch Persistent before ClassSecurityInfo is used
53
+ Persistent.__class_init__ = InitializeClass
54
+
55
+ LOG = getLogger('SecurityInfo')
56
+
57
+ # Security constants - these are imported into the AccessControl
58
+ # namespace and can be referenced as AccessControl.PUBLIC etc.
59
+
60
+ ACCESS_NONE = _what_not_even_god_should_do
61
+ ACCESS_PRIVATE = ()
62
+ ACCESS_PUBLIC = None
63
+
64
+ _marker = []
65
+
66
+
67
+ class SecurityInfo(Implicit):
68
+ """Encapsulate security information."""
69
+
70
+ __security_info__ = 1
71
+
72
+ __roles__ = ACCESS_PRIVATE
73
+
74
+ def __init__(self):
75
+ self.names = {}
76
+ self.roles = {}
77
+ self._unused_protected_decorators = set()
78
+
79
+ def _setaccess(self, names, access):
80
+ for name in names:
81
+ if self.names.get(name, access) != access:
82
+ LOG.warning(
83
+ f'Conflicting security declarations for {name!r}')
84
+ self._warnings = 1
85
+ self.names[name] = access
86
+
87
+ declarePublic__roles__ = ACCESS_PRIVATE
88
+
89
+ def declarePublic(self, name, *names):
90
+ """Declare names to be publicly accessible."""
91
+ self._setaccess((name,) + names, ACCESS_PUBLIC)
92
+
93
+ declarePrivate__roles__ = ACCESS_PRIVATE
94
+
95
+ def declarePrivate(self, name, *names):
96
+ """Declare names to be inaccessible to restricted code."""
97
+ self._setaccess((name,) + names, ACCESS_PRIVATE)
98
+
99
+ declareProtected__roles__ = ACCESS_PRIVATE
100
+
101
+ def declareProtected(self, permission_name, name, *names):
102
+ """Declare names to be associated with a permission."""
103
+ self._setaccess((name,) + names, permission_name)
104
+
105
+ declareObjectPublic__roles__ = ACCESS_PRIVATE
106
+
107
+ def declareObjectPublic(self):
108
+ """Declare the object to be publicly accessible."""
109
+ self._setaccess(('',), ACCESS_PUBLIC)
110
+
111
+ declareObjectPrivate__roles__ = ACCESS_PRIVATE
112
+
113
+ def declareObjectPrivate(self):
114
+ """Declare the object to be inaccessible to restricted code."""
115
+ self._setaccess(('',), ACCESS_PRIVATE)
116
+
117
+ declareObjectProtected__roles__ = ACCESS_PRIVATE
118
+
119
+ def declareObjectProtected(self, permission_name):
120
+ """Declare the object to be associated with a permission."""
121
+ self._setaccess(('',), permission_name)
122
+
123
+ public__roles__ = ACCESS_PRIVATE
124
+
125
+ def public(self, func):
126
+ """Decorate a function to be publicly accessible."""
127
+ self.declarePublic(func.__name__) # NOQA: D001
128
+ return func
129
+
130
+ private__roles__ = ACCESS_PRIVATE
131
+
132
+ def private(self, func):
133
+ """Decorate a function to be inaccessible to restricted code."""
134
+ self.declarePrivate(func.__name__) # NOQA: D001
135
+ return func
136
+
137
+ protected__roles__ = ACCESS_PRIVATE
138
+
139
+ def protected(self, permission_name):
140
+ """Return a decorator to associate a function with a permission."""
141
+ # the decorator returned is remembered in a set and will
142
+ # remove itself upon call. self.apply will check for an empty
143
+ # set and raise an AssertionError otherwise.
144
+ key = f"'{permission_name}':{id(lambda x: x)}"
145
+
146
+ def decor(func):
147
+ self.declareProtected(permission_name, func.__name__) # NOQA: D001
148
+ self._unused_protected_decorators.remove(key)
149
+ return func
150
+ # make sure our key algo creates unique-enough keys
151
+ if key in self._unused_protected_decorators:
152
+ raise KeyError(f"Duplicate key: {key}")
153
+ self._unused_protected_decorators.add(key)
154
+ return decor
155
+
156
+ setPermissionDefault__roles__ = ACCESS_PRIVATE
157
+
158
+ def setPermissionDefault(self, permission_name, roles):
159
+ """Declare default roles for a permission"""
160
+ rdict = {}
161
+ for role in roles:
162
+ rdict[role] = 1
163
+ if self.roles.get(permission_name, rdict) != rdict:
164
+ LOG.warning('Conflicting default role'
165
+ ' declarations for permission "%s"' % permission_name)
166
+ self._warnings = 1
167
+ self.roles[permission_name] = rdict
168
+
169
+ setDefaultAccess__roles__ = ACCESS_PRIVATE
170
+
171
+ def setDefaultAccess(self, access):
172
+ """Declare default attribute access policy.
173
+
174
+ This should be a boolean value, a map of attribute names to
175
+ booleans, or a callable (name, value) -> boolean.
176
+ """
177
+ if isinstance(access, str):
178
+ access = access.lower()
179
+ if access == 'allow':
180
+ access = 1
181
+ elif access == 'deny':
182
+ access = 0
183
+ else:
184
+ raise ValueError("'allow' or 'deny' expected")
185
+ self.access = access
186
+
187
+
188
+ class ClassSecurityInfo(SecurityInfo):
189
+ """Encapsulate security information for class objects."""
190
+
191
+ __roles__ = ACCESS_PRIVATE
192
+
193
+ apply__roles__ = ACCESS_PRIVATE
194
+
195
+ def apply(self, classobj):
196
+ """Apply security information to the given class object."""
197
+
198
+ # make sure all decorators handed out by security.protected were used
199
+ if self._unused_protected_decorators:
200
+ msg = "Class '%r' has %d non-decorator security.protected calls!"
201
+ raise AssertionError(msg % (classobj,
202
+ len(self._unused_protected_decorators)))
203
+
204
+ cdict = classobj.__dict__
205
+
206
+ # Check the class for an existing __ac_permissions__ and
207
+ # incorporate that if present to support older classes or
208
+ # classes that haven't fully switched to using SecurityInfo.
209
+ if '__ac_permissions__' in cdict:
210
+ for item in cdict['__ac_permissions__']:
211
+ permission_name = item[0]
212
+ self._setaccess(item[1], permission_name)
213
+ if len(item) > 2:
214
+ self.setPermissionDefault(permission_name, item[2])
215
+
216
+ # Set __roles__ for attributes declared public or private.
217
+ # Collect protected attribute names in ac_permissions.
218
+ ac_permissions = {}
219
+ for name, access in self.names.items():
220
+ if access in (ACCESS_PRIVATE, ACCESS_PUBLIC, ACCESS_NONE):
221
+ setattr(classobj, '%s__roles__' % name, access)
222
+ else:
223
+ if access not in ac_permissions:
224
+ ac_permissions[access] = []
225
+ ac_permissions[access].append(name)
226
+
227
+ # Now transform our nested dict structure into the nested tuple
228
+ # structure expected of __ac_permissions__ attributes and set
229
+ # it on the class object.
230
+ getRoles = self.roles.get
231
+ __ac_permissions__ = []
232
+ permissions = sorted(ac_permissions.items())
233
+ for permission_name, names in permissions:
234
+ roles = getRoles(permission_name, ())
235
+ if len(roles):
236
+ entry = (permission_name, tuple(names), tuple(roles.keys()))
237
+ else:
238
+ entry = (permission_name, tuple(names))
239
+ __ac_permissions__.append(entry)
240
+ for permission_name, roles in self.roles.items():
241
+ if permission_name not in ac_permissions:
242
+ entry = (permission_name, (), tuple(roles.keys()))
243
+ __ac_permissions__.append(entry)
244
+ setattr(classobj, '__ac_permissions__', tuple(__ac_permissions__))
245
+
246
+ # Take care of default attribute access policy
247
+ access = getattr(self, 'access', _marker)
248
+ if access is not _marker:
249
+ setattr(classobj, '__allow_access_to_unprotected_subobjects__',
250
+ access)
251
+
252
+ if getattr(self, '_warnings', None):
253
+ LOG.warning('Class "%s" had conflicting'
254
+ ' security declarations' % classobj.__name__)
255
+
256
+
257
+ class ClassSecurityInformation(ClassSecurityInfo):
258
+ # Default policy is disallow
259
+ access = 0
260
+
261
+
262
+ _moduleSecurity = frozen.FreezableDict()
263
+ _appliedModuleSecurity = frozen.FreezableDict()
264
+
265
+
266
+ def secureModule(mname, *imp):
267
+ modsec = _moduleSecurity.get(mname, None)
268
+ if modsec is None:
269
+ if mname in _appliedModuleSecurity:
270
+ return sys.modules[mname]
271
+ return # no MSI, no module
272
+
273
+ if imp:
274
+ __import__(mname, *imp)
275
+ module = sys.modules[mname]
276
+ modsec.apply(module.__dict__)
277
+ _appliedModuleSecurity[mname] = modsec
278
+ try:
279
+ del _moduleSecurity[mname]
280
+ except KeyError:
281
+ # In case of access from multiple threads, the del might fail, but that
282
+ # is OK.
283
+ pass
284
+ return module
285
+
286
+
287
+ def ModuleSecurityInfo(module_name=None):
288
+ if module_name is not None:
289
+ modsec = _moduleSecurity.get(module_name, None)
290
+ if modsec is not None:
291
+ return modsec
292
+ modsec = _appliedModuleSecurity.get(module_name, None)
293
+ if modsec is not None:
294
+ # Move security info back to to-apply dict (needed for product
295
+ # refresh). Also invoke this check for parent packages already
296
+ # applied
297
+ del _appliedModuleSecurity[module_name]
298
+ _moduleSecurity[module_name] = modsec
299
+ dot = module_name.rfind('.')
300
+ if dot > 0:
301
+ ModuleSecurityInfo(module_name[:dot])
302
+ return modsec
303
+ dot = module_name.rfind('.')
304
+ if dot > 0:
305
+ # If the module is in a package, recursively make sure
306
+ # there are security declarations for the package steps
307
+ # leading to the module
308
+ modname = module_name[dot + 1:]
309
+ pmodsec = ModuleSecurityInfo(module_name[:dot])
310
+ if modname not in pmodsec.names:
311
+ pmodsec.declarePublic(modname) # NOQA: D001
312
+ return _ModuleSecurityInfo(module_name)
313
+
314
+
315
+ class _ModuleSecurityInfo(SecurityInfo):
316
+ """Encapsulate security information for modules."""
317
+
318
+ __roles__ = ACCESS_PRIVATE
319
+ access = False # deny by default, prevent acquiring 'access' from module
320
+
321
+ def __init__(self, module_name=None):
322
+ self.names = {}
323
+ if module_name is not None:
324
+ global _moduleSecurity # noqa: F824
325
+ _moduleSecurity[module_name] = self
326
+
327
+ __call____roles__ = ACCESS_PRIVATE
328
+
329
+ def __call__(self, name, value):
330
+ """Callback for __allow_access_to_unprotected_subobjects__ hook."""
331
+ access = self.names.get(name, _marker)
332
+ if access is not _marker:
333
+ return access == ACCESS_PUBLIC
334
+
335
+ return getattr(self, 'access', 0)
336
+
337
+ def _setaccess(self, names, access):
338
+ frozen.check_not_frozen()
339
+ super()._setaccess(names, access)
340
+
341
+ setDefaultAccess__roles__ = ACCESS_PRIVATE
342
+
343
+ def setDefaultAccess(self, access):
344
+ """Declare default attribute access policy."""
345
+ frozen.check_not_frozen()
346
+ super().setDefaultAccess(access)
347
+
348
+ apply__roles__ = ACCESS_PRIVATE
349
+
350
+ def apply(self, dict):
351
+ """Apply security information to the given module dict."""
352
+
353
+ # Start with default attribute access policy
354
+ access = getattr(self, 'access', _marker)
355
+ if access is not _marker or len(self.names):
356
+ dict['__allow_access_to_unprotected_subobjects__'] = self
357
+
358
+ if getattr(self, '_warnings', None):
359
+ LOG.warning('Module "%s" had conflicting'
360
+ ' security declarations' % dict['__name__'])
361
+
362
+ declareProtected__roles__ = ACCESS_PRIVATE
363
+
364
+ def declareProtected(self, permission_name, *names):
365
+ """Cannot declare module names protected."""
366
+ pass
367
+
368
+ declareObjectProtected__roles__ = ACCESS_PRIVATE
369
+
370
+ def declareObjectProtected(self, permission_name):
371
+ """Cannot declare module protected."""
372
+ pass
373
+
374
+ setDefaultRoles__roles__ = ACCESS_PRIVATE
375
+
376
+ def setDefaultRoles(self, permission_name, roles):
377
+ """Cannot set default roles for permissions in a module."""
378
+ pass
379
+
380
+ # Handy little utility functions
381
+
382
+
383
+ def allow_module(module_name):
384
+ """Allow a module and all its contents to be used from a
385
+ restricted Script. The argument module_name may be a simple
386
+ or dotted module or package name. Note that if a package
387
+ path is given, all modules in the path will be available."""
388
+ ModuleSecurityInfo(module_name).setDefaultAccess(1)
389
+ dot = module_name.find('.')
390
+ while dot > 0:
391
+ ModuleSecurityInfo(module_name[:dot]).setDefaultAccess(1)
392
+ dot = module_name.find('.', dot + 1)
393
+
394
+
395
+ allow_module.__roles__ = ACCESS_PRIVATE
396
+
397
+ # Modules that should never be fully accessible from restricted code.
398
+ # A declaration for one of these, or a submodule, is logged by
399
+ # check_dangerous_modules, which freeze_security_declarations calls.
400
+ # PLEASE NOTE: This listing cannot ever be complete and it cannot guard
401
+ # against malicious or sloppy code exposing other unsafe modules! Its
402
+ # purpose is just informational, it is not a safe catch-all.
403
+ DANGEROUS_MODULES = frozenset((
404
+ # processes and code execution
405
+ '_posixsubprocess', '_thread', 'asyncio', 'atexit', 'bdb', 'builtins',
406
+ 'code', 'codeop', 'concurrent', 'copyreg', 'cProfile', 'ctypes',
407
+ '_ctypes', 'doctest', 'faulthandler', 'gc', 'importlib', 'inspect',
408
+ 'logging', 'marshal', 'multiprocessing', 'nt', 'operator', 'os', 'pdb',
409
+ 'pickle', '_pickle', 'pkgutil', 'posix', 'profile', 'pty', 'pydoc',
410
+ 'runpy', 'shelve', 'signal', 'site', 'subprocess', 'sys', 'threading',
411
+ 'timeit', 'trace', 'traceback', 'types', 'unittest', 'webbrowser',
412
+ 'zipimport',
413
+ # filesystem
414
+ 'bz2', 'codecs', 'compileall', 'configparser', 'dbm', 'ensurepip',
415
+ 'fcntl', 'filecmp', 'fileinput', 'genericpath', 'glob', 'gzip', 'io',
416
+ '_io', 'linecache', 'lzma', 'mailbox', 'mmap', 'netrc', 'ntpath',
417
+ 'pathlib', 'posixpath', 'py_compile', 'shutil', 'sqlite3', 'sysconfig',
418
+ 'tarfile', 'tempfile', 'venv', 'zipapp', 'zipfile',
419
+ # network
420
+ 'ftplib', 'http', 'imaplib', 'poplib', 'select', 'selectors', 'smtplib',
421
+ 'socket', 'socketserver', 'ssl', 'urllib', 'wsgiref', 'xmlrpc',
422
+ # information about the system, or process wide state
423
+ 'getpass', 'grp', 'locale', 'platform', 'pwd', 'resource',
424
+ # Zope: security declarations and policy, switching users or sites,
425
+ # transactions, the database
426
+ 'AccessControl', 'App', 'transaction', 'ZODB', 'Zope2',
427
+ 'zope.component.hooks', 'zope.interface',
428
+ # third-party network libraries: requests from the server itself can
429
+ # reach internal services, and httpx can use local Unix sockets
430
+ 'aiohttp', 'httpx', 'pycurl', 'requests', 'urllib3',
431
+ ))
432
+
433
+
434
+ def freeze_security_declarations(dangerous_modules=DANGEROUS_MODULES):
435
+ """Refuse changes to security declarations from now on.
436
+
437
+ Call this once all code has been loaded, for example when Zope has
438
+ started. Afterwards, ModuleSecurityInfo, allow_module, allow_class and
439
+ allow_type raise Forbidden for any change, so new modules, classes and
440
+ types cannot be opened up to restricted code.
441
+
442
+ Normal class security declarations with ClassSecurityInfo still work,
443
+ because classes may be imported later, for example when loading objects
444
+ from the database.
445
+
446
+ Pending declarations are applied first, because importing a module from
447
+ restricted code would otherwise still need to change them. Dangerous
448
+ modules that are fully accessible are logged as a warning, see
449
+ check_dangerous_modules.
450
+
451
+ Calling this when security declarations are already frozen does nothing.
452
+ """
453
+ if frozen.is_frozen():
454
+ return
455
+ # Most of these modules have likely already been imported, because the
456
+ # declarations are usually made in the module itself or its package.
457
+ # So this is fast.
458
+ for name in sorted(_moduleSecurity):
459
+ try:
460
+ secureModule(name, {}, {})
461
+ except ImportError:
462
+ LOG.info(f'Could not import {name!r} to apply its'
463
+ ' module security declarations.')
464
+
465
+ check_dangerous_modules(dangerous_modules)
466
+ frozen.freeze()
467
+
468
+
469
+ def check_dangerous_modules(dangerous_modules=DANGEROUS_MODULES):
470
+ """Log a warning for dangerous modules accessible from restricted code.
471
+
472
+ Only modules that are fully accessible are logged, for example with
473
+ allow_module, not modules where only specific names are public.
474
+ A submodule of a dangerous module is dangerous as well. Pass
475
+ dangerous_modules to check other modules, for example ``{'my.package'}``.
476
+ """
477
+ for name in sorted(set(_moduleSecurity) | set(_appliedModuleSecurity)):
478
+ modsec = _appliedModuleSecurity.get(name) or _moduleSecurity[name]
479
+ access = getattr(modsec, 'access', 0)
480
+ if not access or isinstance(access, dict):
481
+ # Only specific names are accessible.
482
+ continue
483
+ parts = name.split('.')
484
+ for index in range(1, len(parts) + 1):
485
+ if '.'.join(parts[:index]) in dangerous_modules:
486
+ LOG.warning(
487
+ f'Module {name!r} is accessible from restricted code.')
488
+ break
489
+
490
+
491
+ def allow_class(Class):
492
+ """Allow a class and all of its methods to be used from a
493
+ restricted Script. The argument Class must be a class."""
494
+ frozen.check_not_frozen()
495
+ Class._security = sec = ClassSecurityInfo()
496
+ sec.declareObjectPublic()
497
+ sec.setDefaultAccess(1)
498
+ sec.apply(Class)
499
+ InitializeClass(Class)
500
+
501
+
502
+ allow_class.__roles__ = ACCESS_PRIVATE
@@ -0,0 +1,84 @@
1
+ ##############################################################################
2
+ #
3
+ # Copyright (c) 2002 Zope Foundation and Contributors.
4
+ #
5
+ # This software is subject to the provisions of the Zope Public License,
6
+ # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7
+ # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8
+ # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9
+ # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10
+ # FOR A PARTICULAR PURPOSE
11
+ #
12
+ ##############################################################################
13
+ """Security management
14
+ """
15
+
16
+ from _thread import get_ident
17
+
18
+ from AccessControl import SpecialUsers
19
+
20
+
21
+ def getSecurityManager():
22
+ """Get a security manager, for the current thread.
23
+ """
24
+ thread_id = get_ident()
25
+ manager = _managers.get(thread_id, None)
26
+ if manager is None:
27
+ nobody = getattr(SpecialUsers, 'nobody', None)
28
+ if nobody is None:
29
+ # Initialize SpecialUsers by importing User.py.
30
+ from AccessControl import User # NOQA: F401
31
+ nobody = SpecialUsers.nobody
32
+ manager = SecurityManager(thread_id, SecurityContext(nobody)) # NOQA
33
+ _managers[thread_id] = manager
34
+
35
+ return manager
36
+
37
+
38
+ def setSecurityManager(manager):
39
+ """install *manager* as current security manager for this thread."""
40
+ thread_id = get_ident()
41
+ _managers[thread_id] = manager
42
+
43
+
44
+ # AccessControl.Implementation inserts SecurityManager.
45
+
46
+
47
+ _managers = {}
48
+
49
+
50
+ def newSecurityManager(request, user):
51
+ """Set up a new security context for a request for a user
52
+ """
53
+ thread_id = get_ident()
54
+ _managers[thread_id] = SecurityManager( # NOQA: F821
55
+ thread_id,
56
+ SecurityContext(user),
57
+ )
58
+
59
+
60
+ def noSecurityManager():
61
+ try:
62
+ del _managers[get_ident()]
63
+ except BaseException:
64
+ pass
65
+
66
+
67
+ def setSecurityPolicy(aSecurityPolicy):
68
+ """Set the system default security policy.
69
+
70
+ This method should only be caused by system startup code. It should
71
+ never, for example, be called during a web request.
72
+ """
73
+ SecurityManager.setSecurityPolicy(aSecurityPolicy) # NOQA: F821
74
+
75
+
76
+ class SecurityContext:
77
+ """The security context is an object used internally to the security
78
+ machinery. It captures data about the current security context.
79
+ """
80
+
81
+ def __init__(self, user):
82
+ self.stack = []
83
+ self.user = user
84
+ self.objectCache = {}
@@ -0,0 +1,30 @@
1
+ ##############################################################################
2
+ #
3
+ # Copyright (c) 2002 Zope Foundation and Contributors.
4
+ #
5
+ # This software is subject to the provisions of the Zope Public License,
6
+ # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7
+ # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8
+ # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9
+ # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10
+ # FOR A PARTICULAR PURPOSE
11
+ #
12
+ ##############################################################################
13
+ '''API module to set the security policy
14
+ '''
15
+
16
+ from AccessControl import ImplPython as _ImplPython
17
+
18
+
19
+ def setSecurityPolicy(aSecurityPolicy):
20
+ """Set the system default security policy.
21
+
22
+ This method should only be caused by system startup code. It should
23
+ never, for example, be called during a web request.
24
+ """
25
+ last = _ImplPython._defaultPolicy
26
+ _ImplPython._defaultPolicy = aSecurityPolicy
27
+ return last
28
+
29
+
30
+ # AccessControl.Implementation inserts SecurityManager.