zope.security-4.0.3/0000775000175000017500000000000012533437256015521 5ustar tseavertseaver00000000000000zope.security-4.0.3/TODO-4.0.txt0000664000175000017500000000026512450532147017322 0ustar tseavertseaver000000000000004.0.0 TODO ---------- - TODO: Add PyPy support - TODO: add pure-Python implementations of: - ``z.s._proxy.getChecker`` - ``z.s._proxy.getObject`` - ``z.s._proxy._Proxy`` zope.security-4.0.3/setup.cfg0000664000175000017500000000044012533437256017340 0ustar tseavertseaver00000000000000[nosetests] nocapture = 1 cover-package = zope.security cover-erase = 1 with-doctest = 0 where = src exclude = untrustedpython [aliases] dev = develop easy_install zope.security[testing] docs = easy_install zope.security[docs] [egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 zope.security-4.0.3/buildout.cfg0000664000175000017500000000104612450532147020023 0ustar tseavertseaver00000000000000[buildout] develop = . parts = test python coverage-test coverage-report [test] recipe = zc.recipe.testrunner eggs = zope.security [test,zcml,pytz] [python] recipe = zc.recipe.egg eggs = zope.security [test,zcml,pytz,untrustedpython] interpreter = python [coverage-test] recipe = zc.recipe.testrunner eggs = zope.security [test] defaults = ['--coverage', '../../coverage'] [coverage-report] recipe = zc.recipe.egg eggs = z3c.coverage scripts = coverage=coverage-report arguments = ('coverage', 'coverage/report') zope.security-4.0.3/PKG-INFO0000664000175000017500000004464312533437256016631 0ustar tseavertseaver00000000000000Metadata-Version: 1.1 Name: zope.security Version: 4.0.3 Summary: Zope Security Framework Home-page: http://pypi.python.org/pypi/zope.security Author: Zope Foundation and Contributors Author-email: zope-dev@zope.org License: ZPL 2.1 Description: ``zope.security`` ================= .. image:: https://pypip.in/version/zope.security/badge.svg?style=flat :target: https://pypi.python.org/pypi/zope.security/ :alt: Latest Version .. image:: https://travis-ci.org/zopefoundation/zope.security.png?branch=master :target: https://travis-ci.org/zopefoundation/zope.security .. image:: https://readthedocs.org/projects/zopesecurity/badge/?version=latest :target: http://zopesecurity.readthedocs.org/en/latest/ :alt: Documentation Status The Security framework provides a generic mechanism to implement security policies on Python objects. Changes ======= 4.0.3 (2015-06-02) ------------------ - Fix iteration over security proxies in Python 3 using the pure-Python implementation. 4.0.2 (2015-06-02) ------------------ - Fix compatibility with ``zope.proxy`` 4.1.5 under PyPy. - Fix the very first call to ``removeSecurityProxy`` returning incorrect results if given a proxy under PyPy. 4.0.1 (2014-03-19) ------------------ - Add support for Python 3.4. 4.0.0 (2013-07-09) ------------------ - Update ``boostrap.py`` to version 2.2. - Bugfix: ZOPE_WATCH_CHECKERS=2 used to incorrectly suppress unauthorized/forbidden warnings. - Bugfix: ZOPE_WATCH_CHECKERS=1 used to miss most of the checks. 4.0.0b1 (2013-03-11) -------------------- - Add support for PyPy. - Fix extension compilation on windows python 3.x 4.0.0a5 (2013-02-28) -------------------- - Undo changes from 4.0.0a4. Instead, ``zope.untrustedpython`` is only included during Python 2 installs. 4.0.0a4 (2013-02-28) -------------------- - Remove ``untrustedpython`` extra again, since we do not want to support ``zope.untrustedpython`` in ZTK 2.0. If BBB is really needed, we will create a 3.10.0 release. 4.0.0a3 (2013-02-15) -------------------- - Fix test breakage in 4.0.0a2 due to deprecation strategy. 4.0.0a2 (2013-02-15) -------------------- - Add back the ``untrustedpython`` extra: now pulls in ``zope.untrustedpython``. Restored deprecated backward-compatible imports for ``zope.security.untrustedpython.{builtins,interpreter,rcompile}`` (the extra and the imports are to be removed in version 4.1). 4.0.0a1 (2013-02-14) -------------------- - Add support for Python 3.2 and 3.3. - Bring unit test coverage to 100%. - ``zope.security.untrustedpython`` moved to separate project: ``zope.untrustedpython`` - Convert use of ``assert`` in non-test code to apprpriate error types: - Non-dict's passed to ``Checker.__init__``. - Remove dprecattion of ``zope.security.adapter.TrustedAdapterFactory``. Although it has been marked as deprectaed since before Zope3 3.2, current versions of ``zope.compoent`` still rely on it. - Convert doctests to Sphinx documentation in 'docs'. - Add ``setup.py docs`` alias (installs ``Sphinx`` and dependencies). - Add ``setup.py dev`` alias (runs ``setup.py develop`` plus installs ``nose`` and ``coverage``). - Make non-doctest tests fully independent of ``zope.testing``. Two modules, ``zope.security.checker`` and ``zope.security.management``, register cleanups with ``zope.testing`` IFF it is importable, but the tests no longer rely on it. - Enable building extensions without the ``svn:external`` of the ``zope.proxy`` headers into our ``include`` dir. - Bump ``zope.proxy`` dependency to ">= 4.1.0" to enable compilation on Py3k. - Replace deprecated ``zope.component.adapts`` usage with equivalent ``zope.component.adapter`` decorator. - Replace deprecated ``zope.interface.classProvides`` usage with equivalent ``zope.interface.provider`` decorator. - Replace deprecated ``zope.interface.implements`` usage with equivalent ``zope.interface.implementer`` decorator. - Drop support for Python 2.4 and 2.5. - Add test convenience helper ``create_interaction`` and ``with interaction()``. 3.9.0 (2012-12-21) ------------------ - Pin ``zope.proxy >= 4.1.0`` - Ship with an included ``proxy.h`` header which is compatible with the 4.1.x version ov ``zope.proxy``. 3.8.5 (2012-12-21) ------------------ - Ship with an included ``proxy.h`` header which is compatible with the supported versions of ``zope.proxy``. 3.8.4 (2012-12-20) ------------------ - Pin ``zope.proxy >= 3.4.2, <4.1dev`` 3.8.3 (2011-09-24) ------------------ - Fix a regression introduced in 3.8.1: ``zope.location``\'s LocationProxy did not get a security checker if ``zope.security.decorator`` was not imported manually. Now ``zope.security.decorator`` is imported in ``zope.security.proxy`` without re-introducing the circular import fixed in 3.8.1. 3.8.2 (2011-05-24) ------------------ - Fix a test that failed on Python 2.7. 3.8.1 (2011-05-03) ------------------ - Fix circular import beween ``zope.security.decorator`` and ``zope.security.proxy`` which led to an ``ImportError`` when only importing ``zope.security.decorator``. 3.8.0 (2010-12-14) ------------------ - Add tests for our own ``configure.zcml``. - Add ``zcml`` extra dependencies; run related tests only if ``zope.configuration`` is available. - Run tests related to the ``untrustedpython`` functionality only if ``RestrictedPython`` is available. 3.7.3 (2010-04-30) ------------------ - Prefer the standard library's ``doctest`` module to the one from ``zope.testing``. - Ensure ``PermissionIdsVocabulary`` directly provides ``IVocabularyFactory``, even though it might be unnecessary because ``IVocabularyFactory`` is provided in ZCML. - Remove the dependency on the zope.exceptions package: zope.security.checker now imports ``DuplicationError`` from zope.exceptions if available, otherwise it defines a package-specific ``DuplicationError`` class which inherits from Exception. 3.7.2 (2009-11-10) ------------------ - Add compatibility with Python 2.6 abstract base classes. 3.7.1 (2009-08-13) ------------------ - Fix for LP bug 181833 (from Gustavo Niemeyer). Before "visiting" a sub-object, a check should be made to ensure the object is still valid. Because garbage collection may involve loops, if you garbage collect an object, it is possible that the actions done on this object may modify the state of other objects. This may cause another round of garbage collection, eventually generating a segfault (see LP bug). The Py_VISIT macro does the necessary checks, so it is used instead of the previous code. 3.7.0 (2009-05-13) ------------------ - Make ``pytz`` a soft dependency: the checker for ``pytz.UTC`` is created / tested only if the package is already present. Run ``bin/test_pytz`` to run the tests with ``pytz`` on the path. 3.6.3 (2009-03-23) ------------------ - Ensure that simple zope.schema's ``VocabularyRegistry`` is used for ``PermissionVocabulary`` tests, because it's replaced implicitly in environments with ``zope.app.schema`` installed that makes that tests fail. - Fix a bug in ``DecoratedSecurityCheckerDescriptor`` which made security-wrapping location proxied exception instances throw exceptions on Python 2.5. See https://bugs.launchpad.net/zope3/+bug/251848 3.6.2 (2009-03-14) ------------------ - Add ``zope.i18nmessageid.Message`` to non-proxied basic types. It's okay, because messages are immutable. Done previously by ``zope.app.security``. - Add ``__name__`` and ``__parent__`` attributes to list of available by default. Done previously by ``zope.app.security``. - Move ``PermissionsVocabulary`` and ``PermissionIdsVocabulary`` vocabularies to the ``zope.security.permission`` module from the ``zope.app.security`` package. - Add zcml permission definitions for most common and useful permissions, like ``zope.View`` and ``zope.ManageContent``, as well as for the special ``zope.Public`` permission. They are placed in a separate ``permissions.zcml`` file, so it can be easily excluded/redefined. They are selected part of permissions moved from ``zope.app.security`` and used by many ``zope.*`` packages. - Add ``addCheckerPublic`` helper function in ``zope.security.testing`` module that registers the "zope.Public" permission as an IPermission utility. - Add security declarations for the ``zope.security.permisson.Permission`` class. - Improve test coverage. 3.6.1 (2009-03-10) ------------------ - Use ``from`` imports instead of ``zope.deferred`` to avoid circular import problems, thus drop dependency on ``zope.deferredimport``. - Raise ``NoInteraction`` when ``zope.security.checkPermission`` is called without interaction being active (LP #301565). - Don't define security checkers for deprecated set types from the "sets" module on Python 2.6. It's discouraged to use them and ``set`` and ``frozenset`` built-in types should be used instead. - Change package's mailng list address to zope-dev at zope.org as zope3-dev at zope.org is now retired. - Remove old zpkg-related files. 3.6.0 (2009-01-31) ------------------ - Install decorated security checker support on ``LocationProxy`` from the outside. - Add support to bootstrap on Jython. - Move the ``protectclass`` module from ``zope.app.security`` to this package to reduce the number of dependencies on ``zope.app.security``. - Move the ```` directive implementation from ``zope.app.security`` to this package. - Move the ```` directive implementation from ``zope.app.component`` to this package. 3.5.2 (2008-07-27) ------------------ - Make C code compatible with Python 2.5 on 64bit architectures. 3.5.1 (2008-06-04) ------------------ - Add ``frozenset``, ``set``, ``reversed``, and ``sorted`` to the list of safe builtins. 3.5.0 (2008-03-05) ------------------ - Changed title for ``zope.security.management.system_user`` to be more presentable. 3.4.3 - (2009/11/26) -------------------- - Backport a fix made by Gary Poster to the 3.4 branch: Fix for LP bug 181833 (from Gustavo Niemeyer). Before "visiting" a sub-object, a check should be made to ensure the object is still valid. Because garbage collection may involve loops, if you garbage collect an object, it is possible that the actions done on this object may modify the state of other objects. This may cause another round of garbage collection, eventually generating a segfault (see LP bug). The ``Py_VISIT`` macro does the necessary checks, so it is used instead of the previous code. 3.4.2 - (2009/03/23) -------------------- - Add dependency on ``zope.thread`` to setup.py; without it, the tests were failing. - Backport a fix made by Albertas Agejevas to the 3.4 branch. He fixed a bug in DecoratedSecurityCheckerDescriptor which made security-wrapping location proxied exception instances throw exceptions on Python 2.5. See https://bugs.launchpad.net/zope3/+bug/251848 3.4.1 - 2008/07/27 ------------------ - Make C code compatible with Python 2.5 on 64bit architectures. 3.4.0 (2007-10-02) ------------------ - Update meta-data. 3.4.0b5 (2007-08-15) -------------------- - Fix a circular import in the C implementation. 3.4.0b4 (2007-08-14) -------------------- - Improve ugly/brittle ID of ``zope.security.management.system_user``. 3.4.0b3 (2007-08-14) -------------------- - Add support for Python 2.5. - Bug: ``zope.security.management.system_user`` wasn't a valid principal (didn't provide IPrincipal). - Bug: Fix inclusion of doctest to use the doctest module from ``zope.testing``. Now tests can be run multiple times without breaking. (#98250) 3.4.0b2 (2007-06-15) -------------------- - Bug: Remove stack extraction in ``newInteraction``. When using eggs this is an extremly expensive function. The publisher is now more than 10 times faster when using eggs and about twice as fast with a zope trunk checkout. 3.4.0b1 ------- - Temporarily fixed the hidden (and accidental) dependency on zope.testing to become optional. Note: The releases between 3.2.0 and 3.4.0b1 where not tracked as an individual package and have been documented in the Zope 3 changelog. 3.2.0 (2006-01-05) ------------------ - Corresponds to the verison of the ``zope.security`` package shipped as part of the Zope 3.2.0 release. - Remove deprecated helper functions, ``proxy.trustedRemoveSecurityProxy`` and ``proxy.getProxiedObject``. - Make handling of ``management.{end,restore}Interaction`` more careful w.r.t. edge cases. - Make behavior of ``canWrite`` consistent with ``canAccess``: if ``canAccess`` does not raise ``ForbiddenAttribute``, then neither will ``canWrite``. See: http://www.zope.org/Collectors/Zope3-dev/506 - Code style / documentation / test fixes. 3.1.0 (2005-10-03) ------------------ - Add support for use of the new Python 2.4 datatypes, ``set`` and ``frozenset``, within checked code. - Make the C security proxy depend on the ``proxy.h`` header from the ``zope.proxy`` package. - XXX: the spelling of the ``#include`` is bizarre! It seems to be related to ``zpkg``-based builds, and should likely be revisited. For the moment, I have linked in the ``zope.proxy`` package into our own ``include`` directory. See the subversion checkin: http://svn.zope.org/Zope3/?rev=37882&view=rev - Update checker to avoid re-proxying objects which have and explicit ``__Security_checker__`` assigned. - Corresponds to the verison of the ``zope.security`` package shipped as part of the Zope 3.1.0 release. - Clarify contract of ``IChecker`` to indicate that its ``check*`` methods may raise only ``Forbidden`` or ``Unauthorized`` exceptions. - Add interfaces, (``IPrincipal``, ``IGroupAwarePrincipal``, ``IGroup``, and ``IPermission``) specifying contracts of components in the security framework. - Code style / documentation / test fixes. 3.0.0 (2004-11-07) ------------------ - Corresponds to the version of the ``zope.security`` package shipped as part of the Zope X3.0.0 release. Keywords: zope security policy principal permission Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Zope Public License Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.2 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Topic :: Internet :: WWW/HTTP Classifier: Framework :: Zope3 zope.security-4.0.3/tox.ini0000664000175000017500000000312012450532147017021 0ustar tseavertseaver00000000000000[tox] envlist = # Jython support pending 2.7 support, due 2012-07-15 or so. See: # http://fwierzbicki.blogspot.com/2012/03/adconion-to-fund-jython-27.html # py26,py27,pypy,jython,py32,py33,coverage,docs py26,py27,py27-pure,pypy,py32,py33,py33-pure,py34,coverage,docs [testenv] deps = zope.interface zope.testing zope.configuration zope.component zope.location zope.proxy zope.testrunner commands = python setup.py test -q [testenv:py27-pure] basepython = python2.7 setenv = PURE_PYTHON = 1 [testenv:py33-pure] basepython = python3.3 setenv = PURE_PYTHON = 1 [testenv:coverage] basepython = python2.6 commands = # The installed version messes up nose's test discovery / coverage reporting # So, we uninstall that from the environment, and then install the editable # version, before running nosetests. pip uninstall -y zope.security python -c "import shutil; shutil.copyfile('src/zope/__init__.py', '{envdir}/lib/python2.6/site-packages/zope/__init__.py')" pip install -e . nosetests --with-xunit --with-xcoverage deps = zope.interface zope.testing zope.configuration zope.component zope.location zope.proxy nose coverage nosexcover [testenv:docs] basepython = python3.3 commands = sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html sphinx-build -b doctest -d docs/_build/doctrees docs docs/_build/doctest deps = zope.interface zope.testing zope.configuration zope.component zope.location zope.proxy Sphinx repoze.sphinx.autointerface zope.security-4.0.3/.gitignore0000664000175000017500000000022512450532147017501 0ustar tseavertseaver00000000000000*.pyc *.so __pycache__ *.egg *.egg-info build docs/_build .installed.cfg bin develop-eggs eggs parts .tox .coverage nosetests.xml coverage.xml .eggs zope.security-4.0.3/setup.py0000664000175000017500000001411312533437213017224 0ustar tseavertseaver00000000000000############################################################################# # # Copyright (c) 2006 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## # This package is developed by the Zope Toolkit project, documented here: # http://docs.zope.org/zopetoolkit # When developing and releasing this package, please follow the documented # Zope Toolkit policies as described by this documentation. ############################################################################## """Setup for zope.security package """ import os import platform import sys from setuptools import Extension from setuptools import find_packages from setuptools import setup TESTS_REQUIRE = [ 'zope.component', 'zope.configuration', 'zope.location', 'zope.testing', 'zope.testrunner', ] def alltests(): import os import sys import unittest # use the zope.testrunner machinery to find all the # test suites we've put under ourselves import zope.testrunner.find import zope.testrunner.options here = os.path.abspath(os.path.join(os.path.dirname(__file__), 'src')) args = sys.argv[:] defaults = ["--test-path", here] options = zope.testrunner.options.get_options(args, defaults) suites = list(zope.testrunner.find.find_suites(options)) return unittest.TestSuite(suites) here = os.path.abspath(os.path.dirname(__file__)) def read(*rnames): return open(os.path.join(os.path.dirname(__file__), *rnames)).read() # Include directories for C extensions # Sniff the location of the headers in 'persistent' or fall back # to local headers in the include sub-directory class ModuleHeaderDir(object): def __init__(self, require_spec, where='../..'): # By default, assume top-level pkg has the same name as the dist. # Also assume that headers are located in the package dir, and # are meant to be included as follows: # #include "module/header_name.h" self._require_spec = require_spec self._where = where def __str__(self): from pkg_resources import require from pkg_resources import resource_filename from pkg_resources import DistributionNotFound try: require(self._require_spec) path = resource_filename(self._require_spec, self._where) except DistributionNotFound: path = os.path.join(here, 'include') return os.path.abspath(path) include = [ModuleHeaderDir('zope.proxy')] # Jython cannot build the C optimizations, while on PyPy they are # anti-optimizations (the C extension compatibility layer is known-slow, # and defeats JIT opportunities). py3 = sys.version_info[0] >= 3 py_impl = getattr(platform, 'python_implementation', lambda: None) pure_python = os.environ.get('PURE_PYTHON', False) is_pypy = py_impl() == 'PyPy' is_jython = 'java' in sys.platform if pure_python or is_pypy or is_jython: setup_requires = [] ext_modules = [] else: setup_requires = ['zope.proxy >= 4.1.0'] ext_modules = [ Extension("zope.security._proxy", [os.path.join('src', 'zope', 'security', "_proxy.c")], include_dirs=include, ), Extension("zope.security._zope_security_checker", [os.path.join('src', 'zope', 'security', "_zope_security_checker.c")] ), ] setup(name='zope.security', version='4.0.3', author='Zope Foundation and Contributors', author_email='zope-dev@zope.org', description='Zope Security Framework', long_description=( read('README.rst') + '\n\n' + read('CHANGES.rst') ), keywords = "zope security policy principal permission", classifiers = [ 'Development Status :: 5 - Production/Stable', 'Environment :: Web Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: Zope Public License', 'Programming Language :: Python', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.2', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', 'Natural Language :: English', 'Operating System :: OS Independent', 'Topic :: Internet :: WWW/HTTP', 'Framework :: Zope3'], url='http://pypi.python.org/pypi/zope.security', license='ZPL 2.1', packages=find_packages('src'), package_dir = {'': 'src'}, namespace_packages=['zope'], setup_requires=setup_requires, ext_modules=ext_modules, install_requires=['setuptools', 'zope.component', 'zope.i18nmessageid', 'zope.interface', 'zope.location', 'zope.proxy >= 4.1.0', 'zope.schema', ], test_suite = '__main__.alltests', tests_require=TESTS_REQUIRE, extras_require = dict( pytz=["pytz"], untrustedpython=['zope.untrustedpython'] if not py3 else [], zcml=['zope.configuration'], test=TESTS_REQUIRE, testing=TESTS_REQUIRE + ['nose', 'coverage'], docs=['Sphinx', 'repoze.sphinx.autointerface'], ), include_package_data = True, zip_safe = False, ) zope.security-4.0.3/bootstrap.py0000664000175000017500000001454512450532147020112 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2006 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Bootstrap a buildout-based project Simply run this script in a directory containing a buildout.cfg. The script accepts buildout command-line options, so you can use the -c option to specify an alternate configuration file. """ import os import shutil import sys import tempfile from optparse import OptionParser tmpeggs = tempfile.mkdtemp() usage = '''\ [DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options] Bootstraps a buildout-based project. Simply run this script in a directory containing a buildout.cfg, using the Python that you want bin/buildout to use. Note that by using --find-links to point to local resources, you can keep this script from going over the network. ''' parser = OptionParser(usage=usage) parser.add_option("-v", "--version", help="use a specific zc.buildout version") parser.add_option("-t", "--accept-buildout-test-releases", dest='accept_buildout_test_releases', action="store_true", default=False, help=("Normally, if you do not specify a --version, the " "bootstrap script and buildout gets the newest " "*final* versions of zc.buildout and its recipes and " "extensions for you. If you use this flag, " "bootstrap and buildout will get the newest releases " "even if they are alphas or betas.")) parser.add_option("-c", "--config-file", help=("Specify the path to the buildout configuration " "file to be used.")) parser.add_option("-f", "--find-links", help=("Specify a URL to search for buildout releases")) parser.add_option("--allow-site-packages", action="store_true", default=False, help=("Let bootstrap.py use existing site packages")) parser.add_option("--setuptools-version", help="use a specific setuptools version") options, args = parser.parse_args() ###################################################################### # load/install setuptools try: if options.allow_site_packages: import setuptools import pkg_resources from urllib.request import urlopen except ImportError: from urllib2 import urlopen ez = {} exec(urlopen('https://bootstrap.pypa.io/ez_setup.py').read(), ez) if not options.allow_site_packages: # ez_setup imports site, which adds site packages # this will remove them from the path to ensure that incompatible versions # of setuptools are not in the path import site # inside a virtualenv, there is no 'getsitepackages'. # We can't remove these reliably if hasattr(site, 'getsitepackages'): for sitepackage_path in site.getsitepackages(): sys.path[:] = [x for x in sys.path if sitepackage_path not in x] setup_args = dict(to_dir=tmpeggs, download_delay=0) if options.setuptools_version is not None: setup_args['version'] = options.setuptools_version ez['use_setuptools'](**setup_args) import setuptools import pkg_resources # This does not (always?) update the default working set. We will # do it. for path in sys.path: if path not in pkg_resources.working_set.entries: pkg_resources.working_set.add_entry(path) ###################################################################### # Install buildout ws = pkg_resources.working_set cmd = [sys.executable, '-c', 'from setuptools.command.easy_install import main; main()', '-mZqNxd', tmpeggs] find_links = os.environ.get( 'bootstrap-testing-find-links', options.find_links or ('http://downloads.buildout.org/' if options.accept_buildout_test_releases else None) ) if find_links: cmd.extend(['-f', find_links]) setuptools_path = ws.find( pkg_resources.Requirement.parse('setuptools')).location requirement = 'zc.buildout' version = options.version if version is None and not options.accept_buildout_test_releases: # Figure out the most recent final version of zc.buildout. import setuptools.package_index _final_parts = '*final-', '*final' def _final_version(parsed_version): try: return not parsed_version.is_prerelease except AttributeError: # Older setuptools for part in parsed_version: if (part[:1] == '*') and (part not in _final_parts): return False return True index = setuptools.package_index.PackageIndex( search_path=[setuptools_path]) if find_links: index.add_find_links((find_links,)) req = pkg_resources.Requirement.parse(requirement) if index.obtain(req) is not None: best = [] bestv = None for dist in index[req.project_name]: distv = dist.parsed_version if _final_version(distv): if bestv is None or distv > bestv: best = [dist] bestv = distv elif distv == bestv: best.append(dist) if best: best.sort() version = best[-1].version if version: requirement = '=='.join((requirement, version)) cmd.append(requirement) import subprocess if subprocess.call(cmd, env=dict(os.environ, PYTHONPATH=setuptools_path)) != 0: raise Exception( "Failed to execute command:\n%s" % repr(cmd)[1:-1]) ###################################################################### # Import and run buildout ws.add_entry(tmpeggs) ws.require(requirement) import zc.buildout.buildout if not [a for a in args if '=' not in a]: args.append('bootstrap') # if -c was provided, we push it back into args for buildout' main function if options.config_file is not None: args[0:0] = ['-c', options.config_file] zc.buildout.buildout.main(args) shutil.rmtree(tmpeggs) zope.security-4.0.3/.travis.yml0000664000175000017500000000051012533121424017611 0ustar tseavertseaver00000000000000language: python sudo: false env: - TOXENV=py26 - TOXENV=py27 - TOXENV=py27-pure - TOXENV=py32 - TOXENV=py33 - TOXENV=py33-pure - TOXENV=py34 - TOXENV=pypy - TOXENV=pypy3 - TOXENV=coverage - TOXENV=docs install: - pip install tox script: - tox notifications: email: false zope.security-4.0.3/src/0000775000175000017500000000000012533437256016310 5ustar tseavertseaver00000000000000zope.security-4.0.3/src/zope.security.egg-info/0000775000175000017500000000000012533437256022625 5ustar tseavertseaver00000000000000zope.security-4.0.3/src/zope.security.egg-info/top_level.txt0000664000175000017500000000000512533437251025345 0ustar tseavertseaver00000000000000zope zope.security-4.0.3/src/zope.security.egg-info/SOURCES.txt0000664000175000017500000001360612533437256024517 0ustar tseavertseaver00000000000000.gitignore .travis.yml CHANGES.rst COPYRIGHT.txt LICENSE.txt MANIFEST.in README.rst TODO-4.0.txt bootstrap.py buildout.cfg rtd.txt setup.cfg setup.py tox.ini docs/Makefile docs/conf.py docs/hacking.rst docs/index.rst docs/make.bat docs/narr.rst docs/_build/doctest/output.txt docs/_build/doctrees/environment.pickle docs/_build/doctrees/hacking.doctree docs/_build/doctrees/index.doctree docs/_build/doctrees/narr.doctree docs/_build/doctrees/api/adapter.doctree docs/_build/doctrees/api/checker.doctree docs/_build/doctrees/api/decorator.doctree docs/_build/doctrees/api/interfaces.doctree docs/_build/doctrees/api/management.doctree docs/_build/doctrees/api/permission.doctree docs/_build/doctrees/api/protectclass.doctree docs/_build/doctrees/api/proxy.doctree docs/_build/doctrees/api/simplepolicies.doctree docs/_build/doctrees/api/testing.doctree docs/_build/doctrees/api/zcml.doctree docs/_build/html/.buildinfo docs/_build/html/genindex.html docs/_build/html/hacking.html docs/_build/html/index.html docs/_build/html/narr.html docs/_build/html/objects.inv docs/_build/html/py-modindex.html docs/_build/html/search.html docs/_build/html/searchindex.js docs/_build/html/_modules/index.html docs/_build/html/_modules/zope/interface/interface.html docs/_build/html/_modules/zope/security/adapter.html docs/_build/html/_modules/zope/security/checker.html docs/_build/html/_modules/zope/security/decorator.html docs/_build/html/_modules/zope/security/interfaces.html docs/_build/html/_modules/zope/security/management.html docs/_build/html/_modules/zope/security/permission.html docs/_build/html/_modules/zope/security/protectclass.html docs/_build/html/_modules/zope/security/proxy.html docs/_build/html/_modules/zope/security/simplepolicies.html docs/_build/html/_modules/zope/security/testing.html docs/_build/html/_modules/zope/security/zcml.html docs/_build/html/_sources/hacking.txt docs/_build/html/_sources/index.txt docs/_build/html/_sources/narr.txt docs/_build/html/_sources/api/adapter.txt docs/_build/html/_sources/api/checker.txt docs/_build/html/_sources/api/decorator.txt docs/_build/html/_sources/api/interfaces.txt docs/_build/html/_sources/api/management.txt docs/_build/html/_sources/api/permission.txt docs/_build/html/_sources/api/protectclass.txt docs/_build/html/_sources/api/proxy.txt docs/_build/html/_sources/api/simplepolicies.txt docs/_build/html/_sources/api/testing.txt docs/_build/html/_sources/api/zcml.txt docs/_build/html/_static/ajax-loader.gif docs/_build/html/_static/basic.css docs/_build/html/_static/classic.css docs/_build/html/_static/comment-bright.png docs/_build/html/_static/comment-close.png docs/_build/html/_static/comment.png docs/_build/html/_static/default.css docs/_build/html/_static/doctools.js docs/_build/html/_static/down-pressed.png docs/_build/html/_static/down.png docs/_build/html/_static/file.png docs/_build/html/_static/jquery-1.11.1.js docs/_build/html/_static/jquery.js docs/_build/html/_static/minus.png docs/_build/html/_static/plus.png docs/_build/html/_static/pygments.css docs/_build/html/_static/searchtools.js docs/_build/html/_static/sidebar.js docs/_build/html/_static/underscore-1.3.1.js docs/_build/html/_static/underscore.js docs/_build/html/_static/up-pressed.png docs/_build/html/_static/up.png docs/_build/html/_static/websupport.js docs/_build/html/api/adapter.html docs/_build/html/api/checker.html docs/_build/html/api/decorator.html docs/_build/html/api/interfaces.html docs/_build/html/api/management.html docs/_build/html/api/permission.html docs/_build/html/api/protectclass.html docs/_build/html/api/proxy.html docs/_build/html/api/simplepolicies.html docs/_build/html/api/testing.html docs/_build/html/api/zcml.html docs/_static/.gitignore docs/api/adapter.rst docs/api/checker.rst docs/api/decorator.rst docs/api/interfaces.rst docs/api/management.rst docs/api/permission.rst docs/api/protectclass.rst docs/api/proxy.rst docs/api/simplepolicies.rst docs/api/testing.rst docs/api/zcml.rst src/coverage.xml src/zope/__init__.py src/zope.security.egg-info/PKG-INFO src/zope.security.egg-info/SOURCES.txt src/zope.security.egg-info/dependency_links.txt src/zope.security.egg-info/namespace_packages.txt src/zope.security.egg-info/not-zip-safe src/zope.security.egg-info/requires.txt src/zope.security.egg-info/top_level.txt src/zope/security/__init__.py src/zope/security/_compat.py src/zope/security/_definitions.py src/zope/security/_proxy.c src/zope/security/_zope_security_checker.c src/zope/security/adapter.py src/zope/security/checker.py src/zope/security/configure.zcml src/zope/security/decorator.py src/zope/security/i18n.py src/zope/security/interfaces.py src/zope/security/management.py src/zope/security/meta.zcml src/zope/security/metaconfigure.py src/zope/security/metadirectives.py src/zope/security/permission.py src/zope/security/permissions.zcml src/zope/security/protectclass.py src/zope/security/proxy.py src/zope/security/setup.py src/zope/security/simplepolicies.py src/zope/security/testing.py src/zope/security/zcml.py src/zope/security/examples/sandbox.py src/zope/security/examples/sandbox_security.py src/zope/security/tests/__init__.py src/zope/security/tests/adapter.py src/zope/security/tests/components.py src/zope/security/tests/emptymodule.py src/zope/security/tests/exampleclass.py src/zope/security/tests/module.py src/zope/security/tests/modulehookup.py src/zope/security/tests/redefineperms.zcml src/zope/security/tests/test_adapter.py src/zope/security/tests/test_checker.py src/zope/security/tests/test_decorator.py src/zope/security/tests/test_location.py src/zope/security/tests/test_management.py src/zope/security/tests/test_metaconfigure.py src/zope/security/tests/test_permission.py src/zope/security/tests/test_protectclass.py src/zope/security/tests/test_proxy.py src/zope/security/tests/test_simpleinteraction.py src/zope/security/tests/test_simplepolicies.py src/zope/security/tests/test_testing.py src/zope/security/tests/test_zcml.py src/zope/security/tests/test_zcml_functest.pyzope.security-4.0.3/src/zope.security.egg-info/PKG-INFO0000664000175000017500000004464312533437251023730 0ustar tseavertseaver00000000000000Metadata-Version: 1.1 Name: zope.security Version: 4.0.3 Summary: Zope Security Framework Home-page: http://pypi.python.org/pypi/zope.security Author: Zope Foundation and Contributors Author-email: zope-dev@zope.org License: ZPL 2.1 Description: ``zope.security`` ================= .. image:: https://pypip.in/version/zope.security/badge.svg?style=flat :target: https://pypi.python.org/pypi/zope.security/ :alt: Latest Version .. image:: https://travis-ci.org/zopefoundation/zope.security.png?branch=master :target: https://travis-ci.org/zopefoundation/zope.security .. image:: https://readthedocs.org/projects/zopesecurity/badge/?version=latest :target: http://zopesecurity.readthedocs.org/en/latest/ :alt: Documentation Status The Security framework provides a generic mechanism to implement security policies on Python objects. Changes ======= 4.0.3 (2015-06-02) ------------------ - Fix iteration over security proxies in Python 3 using the pure-Python implementation. 4.0.2 (2015-06-02) ------------------ - Fix compatibility with ``zope.proxy`` 4.1.5 under PyPy. - Fix the very first call to ``removeSecurityProxy`` returning incorrect results if given a proxy under PyPy. 4.0.1 (2014-03-19) ------------------ - Add support for Python 3.4. 4.0.0 (2013-07-09) ------------------ - Update ``boostrap.py`` to version 2.2. - Bugfix: ZOPE_WATCH_CHECKERS=2 used to incorrectly suppress unauthorized/forbidden warnings. - Bugfix: ZOPE_WATCH_CHECKERS=1 used to miss most of the checks. 4.0.0b1 (2013-03-11) -------------------- - Add support for PyPy. - Fix extension compilation on windows python 3.x 4.0.0a5 (2013-02-28) -------------------- - Undo changes from 4.0.0a4. Instead, ``zope.untrustedpython`` is only included during Python 2 installs. 4.0.0a4 (2013-02-28) -------------------- - Remove ``untrustedpython`` extra again, since we do not want to support ``zope.untrustedpython`` in ZTK 2.0. If BBB is really needed, we will create a 3.10.0 release. 4.0.0a3 (2013-02-15) -------------------- - Fix test breakage in 4.0.0a2 due to deprecation strategy. 4.0.0a2 (2013-02-15) -------------------- - Add back the ``untrustedpython`` extra: now pulls in ``zope.untrustedpython``. Restored deprecated backward-compatible imports for ``zope.security.untrustedpython.{builtins,interpreter,rcompile}`` (the extra and the imports are to be removed in version 4.1). 4.0.0a1 (2013-02-14) -------------------- - Add support for Python 3.2 and 3.3. - Bring unit test coverage to 100%. - ``zope.security.untrustedpython`` moved to separate project: ``zope.untrustedpython`` - Convert use of ``assert`` in non-test code to apprpriate error types: - Non-dict's passed to ``Checker.__init__``. - Remove dprecattion of ``zope.security.adapter.TrustedAdapterFactory``. Although it has been marked as deprectaed since before Zope3 3.2, current versions of ``zope.compoent`` still rely on it. - Convert doctests to Sphinx documentation in 'docs'. - Add ``setup.py docs`` alias (installs ``Sphinx`` and dependencies). - Add ``setup.py dev`` alias (runs ``setup.py develop`` plus installs ``nose`` and ``coverage``). - Make non-doctest tests fully independent of ``zope.testing``. Two modules, ``zope.security.checker`` and ``zope.security.management``, register cleanups with ``zope.testing`` IFF it is importable, but the tests no longer rely on it. - Enable building extensions without the ``svn:external`` of the ``zope.proxy`` headers into our ``include`` dir. - Bump ``zope.proxy`` dependency to ">= 4.1.0" to enable compilation on Py3k. - Replace deprecated ``zope.component.adapts`` usage with equivalent ``zope.component.adapter`` decorator. - Replace deprecated ``zope.interface.classProvides`` usage with equivalent ``zope.interface.provider`` decorator. - Replace deprecated ``zope.interface.implements`` usage with equivalent ``zope.interface.implementer`` decorator. - Drop support for Python 2.4 and 2.5. - Add test convenience helper ``create_interaction`` and ``with interaction()``. 3.9.0 (2012-12-21) ------------------ - Pin ``zope.proxy >= 4.1.0`` - Ship with an included ``proxy.h`` header which is compatible with the 4.1.x version ov ``zope.proxy``. 3.8.5 (2012-12-21) ------------------ - Ship with an included ``proxy.h`` header which is compatible with the supported versions of ``zope.proxy``. 3.8.4 (2012-12-20) ------------------ - Pin ``zope.proxy >= 3.4.2, <4.1dev`` 3.8.3 (2011-09-24) ------------------ - Fix a regression introduced in 3.8.1: ``zope.location``\'s LocationProxy did not get a security checker if ``zope.security.decorator`` was not imported manually. Now ``zope.security.decorator`` is imported in ``zope.security.proxy`` without re-introducing the circular import fixed in 3.8.1. 3.8.2 (2011-05-24) ------------------ - Fix a test that failed on Python 2.7. 3.8.1 (2011-05-03) ------------------ - Fix circular import beween ``zope.security.decorator`` and ``zope.security.proxy`` which led to an ``ImportError`` when only importing ``zope.security.decorator``. 3.8.0 (2010-12-14) ------------------ - Add tests for our own ``configure.zcml``. - Add ``zcml`` extra dependencies; run related tests only if ``zope.configuration`` is available. - Run tests related to the ``untrustedpython`` functionality only if ``RestrictedPython`` is available. 3.7.3 (2010-04-30) ------------------ - Prefer the standard library's ``doctest`` module to the one from ``zope.testing``. - Ensure ``PermissionIdsVocabulary`` directly provides ``IVocabularyFactory``, even though it might be unnecessary because ``IVocabularyFactory`` is provided in ZCML. - Remove the dependency on the zope.exceptions package: zope.security.checker now imports ``DuplicationError`` from zope.exceptions if available, otherwise it defines a package-specific ``DuplicationError`` class which inherits from Exception. 3.7.2 (2009-11-10) ------------------ - Add compatibility with Python 2.6 abstract base classes. 3.7.1 (2009-08-13) ------------------ - Fix for LP bug 181833 (from Gustavo Niemeyer). Before "visiting" a sub-object, a check should be made to ensure the object is still valid. Because garbage collection may involve loops, if you garbage collect an object, it is possible that the actions done on this object may modify the state of other objects. This may cause another round of garbage collection, eventually generating a segfault (see LP bug). The Py_VISIT macro does the necessary checks, so it is used instead of the previous code. 3.7.0 (2009-05-13) ------------------ - Make ``pytz`` a soft dependency: the checker for ``pytz.UTC`` is created / tested only if the package is already present. Run ``bin/test_pytz`` to run the tests with ``pytz`` on the path. 3.6.3 (2009-03-23) ------------------ - Ensure that simple zope.schema's ``VocabularyRegistry`` is used for ``PermissionVocabulary`` tests, because it's replaced implicitly in environments with ``zope.app.schema`` installed that makes that tests fail. - Fix a bug in ``DecoratedSecurityCheckerDescriptor`` which made security-wrapping location proxied exception instances throw exceptions on Python 2.5. See https://bugs.launchpad.net/zope3/+bug/251848 3.6.2 (2009-03-14) ------------------ - Add ``zope.i18nmessageid.Message`` to non-proxied basic types. It's okay, because messages are immutable. Done previously by ``zope.app.security``. - Add ``__name__`` and ``__parent__`` attributes to list of available by default. Done previously by ``zope.app.security``. - Move ``PermissionsVocabulary`` and ``PermissionIdsVocabulary`` vocabularies to the ``zope.security.permission`` module from the ``zope.app.security`` package. - Add zcml permission definitions for most common and useful permissions, like ``zope.View`` and ``zope.ManageContent``, as well as for the special ``zope.Public`` permission. They are placed in a separate ``permissions.zcml`` file, so it can be easily excluded/redefined. They are selected part of permissions moved from ``zope.app.security`` and used by many ``zope.*`` packages. - Add ``addCheckerPublic`` helper function in ``zope.security.testing`` module that registers the "zope.Public" permission as an IPermission utility. - Add security declarations for the ``zope.security.permisson.Permission`` class. - Improve test coverage. 3.6.1 (2009-03-10) ------------------ - Use ``from`` imports instead of ``zope.deferred`` to avoid circular import problems, thus drop dependency on ``zope.deferredimport``. - Raise ``NoInteraction`` when ``zope.security.checkPermission`` is called without interaction being active (LP #301565). - Don't define security checkers for deprecated set types from the "sets" module on Python 2.6. It's discouraged to use them and ``set`` and ``frozenset`` built-in types should be used instead. - Change package's mailng list address to zope-dev at zope.org as zope3-dev at zope.org is now retired. - Remove old zpkg-related files. 3.6.0 (2009-01-31) ------------------ - Install decorated security checker support on ``LocationProxy`` from the outside. - Add support to bootstrap on Jython. - Move the ``protectclass`` module from ``zope.app.security`` to this package to reduce the number of dependencies on ``zope.app.security``. - Move the ```` directive implementation from ``zope.app.security`` to this package. - Move the ```` directive implementation from ``zope.app.component`` to this package. 3.5.2 (2008-07-27) ------------------ - Make C code compatible with Python 2.5 on 64bit architectures. 3.5.1 (2008-06-04) ------------------ - Add ``frozenset``, ``set``, ``reversed``, and ``sorted`` to the list of safe builtins. 3.5.0 (2008-03-05) ------------------ - Changed title for ``zope.security.management.system_user`` to be more presentable. 3.4.3 - (2009/11/26) -------------------- - Backport a fix made by Gary Poster to the 3.4 branch: Fix for LP bug 181833 (from Gustavo Niemeyer). Before "visiting" a sub-object, a check should be made to ensure the object is still valid. Because garbage collection may involve loops, if you garbage collect an object, it is possible that the actions done on this object may modify the state of other objects. This may cause another round of garbage collection, eventually generating a segfault (see LP bug). The ``Py_VISIT`` macro does the necessary checks, so it is used instead of the previous code. 3.4.2 - (2009/03/23) -------------------- - Add dependency on ``zope.thread`` to setup.py; without it, the tests were failing. - Backport a fix made by Albertas Agejevas to the 3.4 branch. He fixed a bug in DecoratedSecurityCheckerDescriptor which made security-wrapping location proxied exception instances throw exceptions on Python 2.5. See https://bugs.launchpad.net/zope3/+bug/251848 3.4.1 - 2008/07/27 ------------------ - Make C code compatible with Python 2.5 on 64bit architectures. 3.4.0 (2007-10-02) ------------------ - Update meta-data. 3.4.0b5 (2007-08-15) -------------------- - Fix a circular import in the C implementation. 3.4.0b4 (2007-08-14) -------------------- - Improve ugly/brittle ID of ``zope.security.management.system_user``. 3.4.0b3 (2007-08-14) -------------------- - Add support for Python 2.5. - Bug: ``zope.security.management.system_user`` wasn't a valid principal (didn't provide IPrincipal). - Bug: Fix inclusion of doctest to use the doctest module from ``zope.testing``. Now tests can be run multiple times without breaking. (#98250) 3.4.0b2 (2007-06-15) -------------------- - Bug: Remove stack extraction in ``newInteraction``. When using eggs this is an extremly expensive function. The publisher is now more than 10 times faster when using eggs and about twice as fast with a zope trunk checkout. 3.4.0b1 ------- - Temporarily fixed the hidden (and accidental) dependency on zope.testing to become optional. Note: The releases between 3.2.0 and 3.4.0b1 where not tracked as an individual package and have been documented in the Zope 3 changelog. 3.2.0 (2006-01-05) ------------------ - Corresponds to the verison of the ``zope.security`` package shipped as part of the Zope 3.2.0 release. - Remove deprecated helper functions, ``proxy.trustedRemoveSecurityProxy`` and ``proxy.getProxiedObject``. - Make handling of ``management.{end,restore}Interaction`` more careful w.r.t. edge cases. - Make behavior of ``canWrite`` consistent with ``canAccess``: if ``canAccess`` does not raise ``ForbiddenAttribute``, then neither will ``canWrite``. See: http://www.zope.org/Collectors/Zope3-dev/506 - Code style / documentation / test fixes. 3.1.0 (2005-10-03) ------------------ - Add support for use of the new Python 2.4 datatypes, ``set`` and ``frozenset``, within checked code. - Make the C security proxy depend on the ``proxy.h`` header from the ``zope.proxy`` package. - XXX: the spelling of the ``#include`` is bizarre! It seems to be related to ``zpkg``-based builds, and should likely be revisited. For the moment, I have linked in the ``zope.proxy`` package into our own ``include`` directory. See the subversion checkin: http://svn.zope.org/Zope3/?rev=37882&view=rev - Update checker to avoid re-proxying objects which have and explicit ``__Security_checker__`` assigned. - Corresponds to the verison of the ``zope.security`` package shipped as part of the Zope 3.1.0 release. - Clarify contract of ``IChecker`` to indicate that its ``check*`` methods may raise only ``Forbidden`` or ``Unauthorized`` exceptions. - Add interfaces, (``IPrincipal``, ``IGroupAwarePrincipal``, ``IGroup``, and ``IPermission``) specifying contracts of components in the security framework. - Code style / documentation / test fixes. 3.0.0 (2004-11-07) ------------------ - Corresponds to the version of the ``zope.security`` package shipped as part of the Zope X3.0.0 release. Keywords: zope security policy principal permission Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Zope Public License Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.2 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Topic :: Internet :: WWW/HTTP Classifier: Framework :: Zope3 zope.security-4.0.3/src/zope.security.egg-info/dependency_links.txt0000664000175000017500000000000112533437251026666 0ustar tseavertseaver00000000000000 zope.security-4.0.3/src/zope.security.egg-info/not-zip-safe0000664000175000017500000000000112450532231025036 0ustar tseavertseaver00000000000000 zope.security-4.0.3/src/zope.security.egg-info/namespace_packages.txt0000664000175000017500000000000512533437251027146 0ustar tseavertseaver00000000000000zope zope.security-4.0.3/src/zope.security.egg-info/requires.txt0000664000175000017500000000064012533437251025220 0ustar tseavertseaver00000000000000setuptools zope.component zope.i18nmessageid zope.interface zope.location zope.proxy >= 4.1.0 zope.schema [docs] Sphinx repoze.sphinx.autointerface [pytz] pytz [test] zope.component zope.configuration zope.location zope.testing zope.testrunner [testing] zope.component zope.configuration zope.location zope.testing zope.testrunner nose coverage [untrustedpython] zope.untrustedpython [zcml] zope.configuration zope.security-4.0.3/src/coverage.xml0000664000175000017500000011662112533413401020616 0ustar tseavertseaver00000000000000 zope.security-4.0.3/src/zope/0000775000175000017500000000000012533437256017265 5ustar tseavertseaver00000000000000zope.security-4.0.3/src/zope/__init__.py0000664000175000017500000000007012450532147021364 0ustar tseavertseaver00000000000000__import__('pkg_resources').declare_namespace(__name__) zope.security-4.0.3/src/zope/security/0000775000175000017500000000000012533437256021134 5ustar tseavertseaver00000000000000zope.security-4.0.3/src/zope/security/checker.py0000664000175000017500000006545012533415227023116 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2003 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Security Checkers You can set the environment variable ZOPE_WATCH_CHECKERS to get additional security checker debugging output on the standard error. Setting ZOPE_WATCH_CHECKERS to 1 will display messages about unauthorized or forbidden attribute access. Setting it to a larger number will also display messages about granted attribute access. Note that the ZOPE_WATCH_CHECKERS mechanism will eventually be replaced with a more general security auditing mechanism. """ import abc import os import sys import types import datetime import decimal import weakref from zope.i18nmessageid import Message import zope.interface.interface import zope.interface.interfaces import zope.interface.declarations from zope.interface import Interface from zope.interface import directlyProvides from zope.interface import implementer from zope.interface.interfaces import IDeclaration from zope.interface.interfaces import IInterface from zope.security.interfaces import IChecker from zope.security.interfaces import INameBasedChecker from zope.security.interfaces import ISecurityProxyFactory from zope.security.interfaces import ForbiddenAttribute from zope.security.interfaces import Unauthorized from zope.security._definitions import thread_local from zope.security._compat import CLASS_TYPES from zope.security._compat import PYTHON2 from zope.security._compat import _u from zope.security.proxy import Proxy from zope.security.proxy import getChecker try: from zope.exceptions import DuplicationError except ImportError: #pragma NO COVER class DuplicationError(Exception): """A duplicate registration was attempted""" if os.environ.get('ZOPE_WATCH_CHECKERS'): #pragma NO COVER try: WATCH_CHECKERS = int(os.environ.get('ZOPE_WATCH_CHECKERS')) except ValueError: WATCH_CHECKERS = 1 else: WATCH_CHECKERS = 0 def ProxyFactory(object, checker=None): """Factory function that creates a proxy for an object The proxy checker is looked up if not provided. """ if type(object) is Proxy: if checker is None or checker is getChecker(object): return object else: # We have a proxy, but someone asked us to change its checker. # Let's raise an exception. # # Other reasonable actions would be to either keep the existing # proxy, or to create a new one with the given checker. # The latter might be a security hole though, if untrusted code # can call ProxyFactory. raise TypeError("Tried to use ProxyFactory to change a Proxy's" " checker.") if checker is None: checker = getattr(object, '__Security_checker__', None) if checker is None: checker = selectChecker(object) if checker is None: return object return Proxy(object, checker) directlyProvides(ProxyFactory, ISecurityProxyFactory) # This import represents part of the API for the proxy module from . import proxy proxy.ProxyFactory = ProxyFactory def canWrite(obj, name): """Check whether the interaction may write an attribute named name on obj. Convenience method. Rather than using checkPermission in high level code, use canWrite and canAccess to avoid binding code to permissions. """ obj = ProxyFactory(obj) checker = getChecker(obj) try: checker.check_setattr(obj, name) except Unauthorized: return False except ForbiddenAttribute: # we are going to be a bit DWIM-y here: see # http://www.zope.org/Collectors/Zope3-dev/506 # generally, if the check is ForbiddenAttribute we want it to be # raised: it probably indicates a programming or configuration error. # However, we special case a write ForbiddenAttribute when one can # actually read the attribute: this represents a reasonable # configuration of a readonly attribute, and returning False (meaning # "no, you can't write it") is arguably more useful than raising the # exception. try: checker.check_getattr(obj, name) # we'll let *this* ForbiddenAttribute fall through, if any. It # means that both read and write are forbidden. except Unauthorized: pass return False # all other exceptions, other than Unauthorized and ForbiddenAttribute, # should be passed through uncaught, as they indicate programmer error return True def canAccess(obj, name): """Check whether the interaction may access an attribute named name on obj. Convenience method. Rather than using checkPermission in high level code, use canWrite and canAccess to avoid binding code to permissions. """ # access attributes and methods, including, in the current checker # implementation, special names like __getitem__ obj = ProxyFactory(obj) checker = getChecker(obj) try: checker.check_getattr(obj, name) except Unauthorized: return False # if it is Forbidden (or anything else), let it be raised: it probably # indicates a programming or configuration error return True @implementer(INameBasedChecker) class CheckerPy(object): def __init__(self, get_permissions, set_permissions=None): """Create a checker A dictionary must be provided for computing permissions for names. The dictionary get will be called with attribute names and must return a permission id, None, or the special marker, CheckerPublic. If None is returned, then access to the name is forbidden. If CheckerPublic is returned, then access will be granted without checking a permission. An optional setattr dictionary may be provided for checking set attribute access. """ if not isinstance(get_permissions, dict): raise TypeError('get_permissions must be a dict') self.get_permissions = get_permissions if set_permissions is not None: if not isinstance(set_permissions, dict): raise TypeError('set_permissions must be a dict') else: set_permissions = {} self.set_permissions = set_permissions def permission_id(self, name): 'See INameBasedChecker' return self.get_permissions.get(name) def setattr_permission_id(self, name): 'See INameBasedChecker' if self.set_permissions: return self.set_permissions.get(name) def check_setattr(self, object, name): 'See IChecker' if self.set_permissions: permission = self.set_permissions.get(name) else: permission = None if permission is not None: if permission is CheckerPublic: return # Public if thread_local.interaction.checkPermission(permission, object): return # allowed else: __traceback_supplement__ = (TracebackSupplement, object) raise Unauthorized(object, name, permission) __traceback_supplement__ = (TracebackSupplement, object) raise ForbiddenAttribute(name, object) def check(self, object, name): 'See IChecker' permission = self.get_permissions.get(name) if permission is not None: if permission is CheckerPublic: return # Public if thread_local.interaction.checkPermission(permission, object): return else: __traceback_supplement__ = (TracebackSupplement, object) raise Unauthorized(object, name, permission) elif name in _available_by_default: return if name != '__iter__' or hasattr(object, name): __traceback_supplement__ = (TracebackSupplement, object) raise ForbiddenAttribute(name, object) check_getattr = check # 'See IChecker' def proxy(self, value): 'See IChecker' if type(value) is Proxy: return value checker = getattr(value, '__Security_checker__', None) if checker is None: checker = selectChecker(value) if checker is None: return value return Proxy(value, checker) Checker = CheckerPy # in case no C optimizations # Helper class for __traceback_supplement__ class TracebackSupplement(object): def __init__(self, obj): self.obj = obj def getInfo(self): result = [] try: cls = self.obj.__class__ if hasattr(cls, "__module__"): s = "%s.%s" % (cls.__module__, cls.__name__) else: #pragma NO COVER XXX s = str(cls.__name__) result.append(" - class: " + s) except: #pragma NO COVER XXX pass try: cls = type(self.obj) if hasattr(cls, "__module__"): s = "%s.%s" % (cls.__module__, cls.__name__) else: #pragma NO COVER XXX s = str(cls.__name__) result.append(" - type: " + s) except: #pragma NO COVER XXX pass return "\n".join(result) class Global(object): """A global object that behaves like a string. We want this to behave as a global, meaning it's pickled by name, rather than value. We need to arrange that it has a suitable __reduce__. """ def __init__(self, name, module=None): if module is None: #pragma NO COVER XXX module = sys._getframe(1).f_locals['__name__'] self.__name__ = name self.__module__ = module def __reduce__(self): return self.__name__ def __repr__(self): return "%s(%s,%s)" % (self.__class__.__name__, self.__name__, self.__module__) # Marker for public attributes CheckerPublic = Global('CheckerPublic') CP_HACK_XXX = CheckerPublic # Now we wrap it in a security proxy so that it retains its # identity when it needs to be security proxied. d = {} CheckerPublic = Proxy(CheckerPublic, Checker(d)) # XXX uses CheckerPy d['__reduce__'] = CheckerPublic d['__module__'] = CheckerPublic del d # TODO: It's a bit scary above that we can pickle a proxy if access is # granted to __reduce__. We might want to bother to prevent this in # general and only allow it in this specific case. def NamesChecker(names=(), permission_id=CheckerPublic, **__kw__): """Return a checker that grants access to a set of names. A sequence of names is given as the first argument. If a second argument, permission_id, is given, it is the permission required to access the names. Additional names and permission ids can be supplied as keyword arguments. """ data = {} data.update(__kw__) for name in names: if data.get(name, permission_id) is not permission_id: raise DuplicationError(name) data[name] = permission_id return Checker(data) def InterfaceChecker(interface, permission_id=CheckerPublic, **__kw__): return NamesChecker(interface.names(all=True), permission_id, **__kw__) def MultiChecker(specs): """Create a checker from a sequence of specifications A specification is: - A two-tuple with: o a sequence of names or an interface o a permission id All the names in the sequence of names or the interface are protected by the permission. - A dictionoid (having an items method), with items that are name/permission-id pairs. """ data = {} for spec in specs: if type(spec) is tuple: names, permission_id = spec if IInterface.providedBy(names): names = names.names(all=True) for name in names: if data.get(name, permission_id) is not permission_id: raise DuplicationError(name) data[name] = permission_id else: for name, permission_id in spec.items(): if data.get(name, permission_id) is not permission_id: raise DuplicationError(name) data[name] = permission_id return Checker(data) def selectCheckerPy(object): """Get a checker for the given object The appropriate checker is returned or None is returned. If the return value is None, then object should not be wrapped in a proxy. """ # We need to be careful here. We might have a proxy, in which case # we can't use the type. OTOH, we might not be able to use the # __class__ either, since not everything has one. # TODO: we really need formal proxy introspection #if type(object) is Proxy: # # Is this already a security proxy? # return None checker = _getChecker(type(object), _defaultChecker) #checker = _getChecker(getattr(object, '__class__', type(object)), # _defaultChecker) if checker is NoProxy: return None while not isinstance(checker, Checker): checker = checker(object) if checker is NoProxy or checker is None: return None return checker selectChecker = selectCheckerPy # in case no C optimizations def getCheckerForInstancesOf(class_): return _checkers.get(class_) DEFINABLE_TYPES = CLASS_TYPES + (types.ModuleType,) def defineChecker(type_, checker): """Define a checker for a given type of object The checker can be a Checker, or a function that, when called with an object, returns a Checker. """ if not isinstance(type_, DEFINABLE_TYPES): raise TypeError( 'type_ must be a type, class or module, not a %s' % type_) if type_ in _checkers: raise DuplicationError(type_) _checkers[type_] = checker def undefineChecker(type_): del _checkers[type_] NoProxy = object() # _checkers is a mapping. # # - Keys are types # # - Values are # # o None => rock # o a Checker # o a function returning None or a Checker # _checkers = {} _defaultChecker = Checker({}) _available_by_default = [] # Get optimized versions try: import zope.security._zope_security_checker except (ImportError, AttributeError): #pragma NO COVER PyPy / PURE_PYTHON pass else: from zope.security._zope_security_checker import _checkers, selectChecker from zope.security._zope_security_checker import NoProxy, Checker from zope.security._zope_security_checker import _defaultChecker from zope.security._zope_security_checker import _available_by_default zope.interface.classImplements(Checker, INameBasedChecker) _getChecker = _checkers.get @implementer(IChecker) class CombinedChecker(Checker): """A checker that combines two other checkers in a logical-or fashion. The following table describes the result of a combined checker in detail. checker1 checker2 CombinedChecker(checker1, checker2) ------------------ ------------------ ----------------------------------- ok anything ok (checker2 is never called) Unauthorized ok ok Unauthorized Unauthorized Unauthorized Unauthorized ForbiddenAttribute Unauthorized ForbiddenAttribute ok ok ForbiddenAttribute Unauthorized Unauthorized ForbiddenAttribute ForbiddenAttribute ForbiddenAttribute ------------------ ------------------ ----------------------------------- """ def __init__(self, checker1, checker2): """Create a combined checker.""" Checker.__init__(self, checker1.get_permissions, checker1.set_permissions) self._checker2 = checker2 def check(self, object, name): 'See IChecker' try: Checker.check(self, object, name) except ForbiddenAttribute: self._checker2.check(object, name) except Unauthorized as unauthorized_exception: try: self._checker2.check(object, name) except ForbiddenAttribute: raise unauthorized_exception check_getattr = __setitem__ = check def check_setattr(self, object, name): 'See IChecker' try: Checker.check_setattr(self, object, name) except ForbiddenAttribute: self._checker2.check_setattr(object, name) except Unauthorized as unauthorized_exception: try: self._checker2.check_setattr(object, name) except ForbiddenAttribute: raise unauthorized_exception class CheckerLoggingMixin(object): """Debugging mixin for checkers. Prints verbose debugging information about every performed check to sys.stderr. If verbosity is set to 1, only displays Unauthorized and Forbidden messages. If verbosity is set to a larger number, displays all messages. """ verbosity = 1 _file = sys.stderr def _log(self, msg, verbosity=1): if self.verbosity >= verbosity: self._file.write('%s\n' % msg) def check(self, object, name): try: super(CheckerLoggingMixin, self).check(object, name) if self.verbosity > 1: if name in _available_by_default: self._log('[CHK] + Always available: %s on %r' % (name, object), 2) else: self._log( '[CHK] + Granted: %s on %r' % (name, object), 2) except Unauthorized: self._log( '[CHK] - Unauthorized: %s on %r' % (name, object)) raise except ForbiddenAttribute: self._log( '[CHK] - Forbidden: %s on %r' % (name, object)) raise def check_getattr(self, object, name): try: super(CheckerLoggingMixin, self).check(object, name) if self.verbosity > 1: if name in _available_by_default: self._log( '[CHK] + Always available getattr: %s on %r' % (name, object), 2) else: self._log( '[CHK] + Granted getattr: %s on %r' % (name, object), 2) except Unauthorized: self._log( '[CHK] - Unauthorized getattr: %s on %r' % (name, object)) raise except ForbiddenAttribute: self._log( '[CHK] - Forbidden getattr: %s on %r' % (name, object)) raise __setitem__ = check_getattr def check_setattr(self, object, name): try: super(CheckerLoggingMixin, self).check_setattr(object, name) if self.verbosity > 1: self._log( '[CHK] + Granted setattr: %s on %r' % (name, object), 2) except Unauthorized: self._log( '[CHK] - Unauthorized setattr: %s on %r' % (name, object)) raise except ForbiddenAttribute: self._log( '[CHK] - Forbidden setattr: %s on %r' % (name, object)) raise if WATCH_CHECKERS: #pragma NO COVER class Checker(CheckerLoggingMixin, Checker): verbosity = WATCH_CHECKERS class CombinedChecker(CheckerLoggingMixin, CombinedChecker): verbosity = WATCH_CHECKERS def _instanceChecker(inst): return _checkers.get(inst.__class__, _defaultChecker) def moduleChecker(module): return _checkers.get(module) _available_by_default[:] = ['__lt__', '__le__', '__eq__', '__gt__', '__ge__', '__ne__', '__hash__', '__nonzero__', '__class__', '__providedBy__', '__implements__', '__repr__', '__conform__', '__name__', '__parent__', ] _callableChecker = NamesChecker(['__str__', '__name__', '__call__']) _typeChecker = NamesChecker( ['__str__', '__name__', '__module__', '__bases__', '__mro__', '__implemented__']) _namedChecker = NamesChecker(['__name__']) _iteratorChecker = NamesChecker(['next', '__next__', '__iter__', '__len__']) _setChecker = NamesChecker(['__iter__', '__len__', '__str__', '__contains__', 'copy', 'difference', 'intersection', 'issubset', 'issuperset', 'symmetric_difference', 'union', '__and__', '__or__', '__sub__', '__xor__', '__rand__', '__ror__', '__rsub__', '__rxor__', '__eq__', '__ne__', '__lt__', '__gt__', '__le__', '__ge__']) class BasicTypes(dict): """Basic Types Dictionary Make sure that checkers are really updated, when a new type is added. """ def __setitem__(self, name, value): super(BasicTypes.__class__, self).__setitem__(name, value) _checkers[name] = value def __delitem__(self, name): super(BasicTypes.__class__, self).__delitem__(name) del _checkers[name] def clear(self): # Make sure you cannot clear the values raise NotImplementedError def update(self, d): super(BasicTypes.__class__, self).update(d) _checkers.update(d) _basic_types = { object: NoProxy, int: NoProxy, float: NoProxy, complex: NoProxy, type(None): NoProxy, str: NoProxy, bytes: NoProxy, Message: NoProxy, # Messages are immutable, so it's okay bool: NoProxy, datetime.timedelta: NoProxy, datetime.datetime: NoProxy, datetime.date: NoProxy, datetime.time: NoProxy, datetime.tzinfo: NoProxy, } if PYTHON2: _basic_types[long] = NoProxy _basic_types[unicode] = NoProxy else: #pragma NO COVER _basic_types[type({}.values())] = NoProxy _basic_types[type({}.keys())] = NoProxy _basic_types[type({}.items())] = NoProxy try: import pytz except ImportError: pass else: #pragma NO COVER _basic_types[type(pytz.UTC)] = NoProxy BasicTypes = BasicTypes(_basic_types) del _basic_types # Available for tests. Located here so it can be kept in sync with BasicTypes. BasicTypes_examples = { object: object(), int: 65536, float: -1.4142, complex: -1.4142j, type(None): None, bytes: b'abc', bool: True, datetime.timedelta: datetime.timedelta(3), datetime.datetime: datetime.datetime(2003, 1, 1), datetime.date: datetime.date(2003, 1, 1), datetime.time: datetime.time(23, 58), Message: Message('message', domain='hello') } if PYTHON2: BasicTypes_examples[unicode] = _u('uabc') BasicTypes_examples[long] = long(65536) class _Sequence(object): #pragma NO COVER def __len__(self): return 0 def __getitem__(self, i): raise IndexError _Declaration_checker = InterfaceChecker( IDeclaration, _implied=CheckerPublic, subscribe=CheckerPublic, unsubscribe=CheckerPublic, __call__=CheckerPublic, ) def f(): #pragma NO COVER yield f _default_checkers = { dict: NamesChecker(['__getitem__', '__len__', '__iter__', 'get', 'has_key', 'copy', '__str__', 'keys', 'values', 'items', 'iterkeys', 'iteritems', 'itervalues', '__contains__']), list: NamesChecker(['__getitem__', '__getslice__', '__len__', '__iter__', '__contains__', 'index', 'count', '__str__', '__add__', '__radd__', ]), set: _setChecker, frozenset: _setChecker, decimal.Decimal: NamesChecker(['__nonzero__', '__cmp__', '__eq__', '__ne__', 'compare', '__hash__', 'as_tuple', '__str__', 'to_eng_string', '__neg__', '__pos__', '__abs__', '__add__', '__radd__', '__sub__', '__rsub__', '__mul__', '__rmul__', '__div__', '__rdiv__', '__rtruediv__', '__divmod__', '__rdivmod__', '__mod__', '__rmod__', 'remainder_near', '__floordiv__', '__rfloordiv__', '__float__', '__int__', '__long__', '__pow__', '__rpow__', 'normalize', 'quantize', 'same_quantum', 'to_integral', 'sqrt', 'max', 'min', 'adjusted']), # YAGNI: () a rock tuple: NamesChecker(['__getitem__', '__getslice__', '__add__', '__radd__', '__contains__', '__len__', '__iter__', '__str__']), Proxy: NoProxy, type(weakref.ref(_Sequence())): NamesChecker(['__call__']), types.FunctionType: _callableChecker, types.MethodType: _callableChecker, types.BuiltinFunctionType: _callableChecker, types.BuiltinMethodType: _callableChecker, type: _typeChecker, types.ModuleType: lambda module: _checkers.get(module, _namedChecker), type(iter([])): _iteratorChecker, # Same types in Python 2.2.1, type(iter(())): _iteratorChecker, # different in Python 2.3. type(iter({})): _iteratorChecker, type(iter(set())): _iteratorChecker, type(iter(_Sequence())): _iteratorChecker, type(f()): _iteratorChecker, type(Interface): InterfaceChecker( IInterface, __str__=CheckerPublic, _implied=CheckerPublic, subscribe=CheckerPublic, ), zope.interface.interface.Method: InterfaceChecker( zope.interface.interfaces.IMethod), zope.interface.declarations.ProvidesClass: _Declaration_checker, zope.interface.declarations.ClassProvides: _Declaration_checker, zope.interface.declarations.Implements: _Declaration_checker, zope.interface.declarations.Declaration: _Declaration_checker, abc.ABCMeta: _typeChecker, } if PYTHON2: _default_checkers[types.ClassType] = _typeChecker _default_checkers[types.InstanceType] = _instanceChecker # slot description _default_checkers[type(().__getslice__)] = _callableChecker _default_checkers[type({}.iteritems())] = _iteratorChecker _default_checkers[type({}.iterkeys())] = _iteratorChecker _default_checkers[type({}.itervalues())] = _iteratorChecker def _clear(): _checkers.clear() _checkers.update(_default_checkers) _checkers.update(BasicTypes) _clear() try: from zope.testing.cleanup import addCleanUp except ImportError: #pragma NO COVER pass else: addCleanUp(_clear) zope.security-4.0.3/src/zope/security/management.py0000664000175000017500000001100312450532147023606 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Default 'ISecurityManagement' and 'IInteractionManagement' implementation """ from zope.interface import moduleProvides from zope.security.checker import CheckerPublic from zope.security.interfaces import IInteractionManagement from zope.security.interfaces import ISecurityManagement from zope.security.interfaces import NoInteraction from zope.security.simplepolicies import ParanoidSecurityPolicy from zope.security._definitions import thread_local from zope.security._definitions import system_user # API? _defaultPolicy = ParanoidSecurityPolicy moduleProvides( ISecurityManagement, IInteractionManagement) # # ISecurityManagement implementation # def getSecurityPolicy(): """Get the system default security policy.""" return _defaultPolicy def setSecurityPolicy(aSecurityPolicy): """Set the system default security policy, and return the previous value. This method should only be called by system startup code. It should never, for example, be called during a web request. """ global _defaultPolicy last, _defaultPolicy = _defaultPolicy, aSecurityPolicy return last # # IInteractionManagement implementation # def queryInteraction(): return getattr(thread_local, 'interaction', None) def getInteraction(): """Get the current interaction.""" try: return thread_local.interaction except AttributeError: raise NoInteraction class ExistingInteraction(ValueError, AssertionError, #BBB ): pass def newInteraction(*participations): """Start a new interaction.""" if queryInteraction() is not None: raise ExistingInteraction("newInteraction called" " while another interaction is active.") thread_local.interaction = getSecurityPolicy()(*participations) def endInteraction(): """End the current interaction.""" try: thread_local.previous_interaction = thread_local.interaction except AttributeError: # if someone does a restore later, it should be restored to not having # an interaction. If there was a previous interaction from a previous # call to endInteraction, it should be removed. try: del thread_local.previous_interaction except AttributeError: pass else: del thread_local.interaction def restoreInteraction(): try: previous = thread_local.previous_interaction except AttributeError: try: del thread_local.interaction except AttributeError: pass else: thread_local.interaction = previous def checkPermission(permission, object, interaction=None): """Return whether security policy allows permission on object. 'permission' is a permission name. 'object' is the object being accessed according to the permission. 'interaction' is an interaction, providing access to information such as authenticated principals. If it is None, the current interaction is used. checkPermission is guaranteed to return True if permission is CheckerPublic or None. """ if permission is CheckerPublic or permission is None: return True if interaction is None: try: interaction = thread_local.interaction except AttributeError: raise NoInteraction return interaction.checkPermission(permission, object) def _clear(): global _defaultPolicy _defaultPolicy = ParanoidSecurityPolicy # XXX This code is used to support automated testing. However, it shouldn't be # here and needs to be refactored. The empty addCleanUp-method is a temporary # workaround to fix packages that depend on zope.security but don't have a # need for zope.testing. try: from zope.testing.cleanup import addCleanUp except ImportError: #pragma NO COVER pass else: addCleanUp(_clear) addCleanUp(endInteraction) zope.security-4.0.3/src/zope/security/testing.py0000664000175000017500000000566612450532147023171 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2004-2011 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Testing support code This module provides some helper/stub objects for setting up interactions. """ import sys import re from zope import interface, component from zope.security import interfaces from zope.security.permission import Permission import contextlib import zope.security.management from zope.testing import renormalizing PY2 = sys.version_info[0] == 2 if PY2: _u = unicode rules = [(re.compile("b('.*?')"), r"\1"), (re.compile('b(".*?")'), r"\1"), ] output_checker = renormalizing.RENormalizing(rules) else: _u = str rules = [(re.compile("u('.*?')"), r"\1"), (re.compile('u(".*?")'), r"\1"), ] output_checker = renormalizing.RENormalizing(rules) @interface.implementer(interfaces.IPrincipal) class Principal: def __init__(self, id, title=None, description='', groups=None): self.id = id self.title = title or id self.description = description if groups is not None: self.groups = groups interface.directlyProvides(self, interfaces.IGroupAwarePrincipal) @interface.implementer(interfaces.IParticipation) class Participation: def __init__(self, principal): self.principal = principal self.interaction = None def addCheckerPublic(): """Add the CheckerPublic permission as 'zope.Public'""" perm = Permission('zope.Public', 'Public', """Special permission used for resources that are always public The public permission is effectively an optimization, sine it allows security computation to be bypassed. """ ) gsm = component.getGlobalSiteManager() gsm.registerUtility(perm, interfaces.IPermission, perm.id) def create_interaction(principal_id, **kw): principal = Principal(principal_id, **kw) participation = Participation(principal) zope.security.management.newInteraction(participation) return principal @contextlib.contextmanager def interaction(principal_id, **kw): if zope.security.management.queryInteraction(): # There already is an interaction. Great. Leave it alone. yield else: principal = create_interaction(principal_id, **kw) try: yield principal finally: zope.security.management.endInteraction() zope.security-4.0.3/src/zope/security/simplepolicies.py0000664000175000017500000000443212450532147024523 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Simple 'ISecurityPolicy' implementations. """ import zope.interface from zope.security.checker import CheckerPublic from zope.security.interfaces import IInteraction from zope.security.interfaces import ISecurityPolicy from zope.security._definitions import system_user @zope.interface.implementer(IInteraction) @zope.interface.provider(ISecurityPolicy) class ParanoidSecurityPolicy(object): """Prohibit all access exctp to public items, or by explicit principals""" def __init__(self, *participations): self.participations = [] for participation in participations: self.add(participation) def add(self, participation): if participation.interaction is not None: raise ValueError("%r already belongs to an interaction" % participation) participation.interaction = self self.participations.append(participation) def remove(self, participation): if participation.interaction is not self: raise ValueError("%r does not belong to this interaction" % participation) self.participations.remove(participation) participation.interaction = None def checkPermission(self, permission, object): if permission is CheckerPublic: return True users = [p.principal for p in self.participations if p.principal is not system_user] return not users @zope.interface.provider(ISecurityPolicy) class PermissiveSecurityPolicy(ParanoidSecurityPolicy): """Allow all access.""" def checkPermission(self, permission, object): return True zope.security-4.0.3/src/zope/security/_compat.py0000664000175000017500000000266612450532147023133 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2013 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """ Python 2 / 3 compatibility """ import platform import os import sys import types py_impl = getattr(platform, 'python_implementation', lambda: None) PYPY = py_impl() == 'PyPy' PURE_PYTHON = os.environ.get('PURE_PYTHON', False) if sys.version_info[0] < 3: #pragma NO COVER from StringIO import StringIO import cPickle as _pickle reload = reload def _u(s): return unicode(s, 'unicode_escape') CLASS_TYPES = (type, types.ClassType) _BUILTINS = '__builtin__' PYTHON3 = False PYTHON2 = True TEXT = unicode else: #pragma NO COVER from io import StringIO import pickle as _pickle from imp import reload def _u(s): return s CLASS_TYPES = (type,) _BUILTINS = 'builtins' PYTHON3 = True PYTHON2 = False TEXT = str _BLANK = _u('') zope.security-4.0.3/src/zope/security/setup.py0000664000175000017500000000147112450532147022642 0ustar tseavertseaver00000000000000#! /usr/bin/env python ############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Security setup """ from distutils.core import setup, Extension setup(name="_Proxy", version = "0.1", ext_modules=[Extension("_Proxy", ["_Proxy.c"])]) zope.security-4.0.3/src/zope/security/meta.zcml0000664000175000017500000000365412450532147022752 0ustar tseavertseaver00000000000000 zope.security-4.0.3/src/zope/security/__init__.py0000664000175000017500000000172212450532147023240 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2004 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Base security system """ from zope.security.management import checkPermission from zope.security.checker import canWrite, canAccess # We need the injection of DecoratedSecurityCheckerDescriptor into # zope.location's LocationProxy as soon someone uses security proxies by # importing zope.security.proxy: import zope.security.decorator zope.security-4.0.3/src/zope/security/permission.py0000664000175000017500000000616012450532147023672 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Permissions """ __docformat__ = "reStructuredText" import operator from zope.component import getUtilitiesFor from zope.component import queryUtility from zope.interface import directlyProvides from zope.interface import implementer from zope.schema.interfaces import IVocabularyFactory from zope.schema.vocabulary import SimpleTerm from zope.schema.vocabulary import SimpleVocabulary from zope.security.checker import CheckerPublic from zope.security.interfaces import IPermission from zope.security._compat import _u @implementer(IPermission) class Permission(object): def __init__(self, id, title="", description=""): self.id = id self.title = title self.description = description def checkPermission(context, permission_id): """Check whether a given permission exists in the provided context. """ if permission_id is CheckerPublic: return if not queryUtility(IPermission, permission_id, context=context): raise ValueError("Undefined permission id", permission_id) def allPermissions(context=None): """Get the ids of all defined permissions """ for id, permission in getUtilitiesFor(IPermission, context): if id != _u('zope.Public'): yield id def PermissionsVocabulary(context=None): """A vocabulary of permission IDs. Term values are permissions, while term tokens are permission IDs. """ terms = [] for id, permission in getUtilitiesFor(IPermission, context): terms.append(SimpleTerm(permission, id)) return SimpleVocabulary(terms) directlyProvides(PermissionsVocabulary, IVocabularyFactory) def PermissionIdsVocabulary(context=None): """A vocabulary of permission IDs. Term values are the permission ID strings except for 'zope.Public', which is the global permission CheckerPublic. Term titles are the permission ID strings except for 'zope.Public', which is shortened to 'Public'. Terms are sorted by title except for 'Public', which always appears as the first term. """ terms = [] has_public = False for name, permission in getUtilitiesFor(IPermission, context): if name == 'zope.Public': has_public = True else: terms.append(SimpleTerm(name, name, name)) terms = sorted(terms, key=operator.attrgetter('title')) if has_public: terms.insert(0, SimpleTerm(CheckerPublic, 'zope.Public', _u('Public'))) return SimpleVocabulary(terms) directlyProvides(PermissionIdsVocabulary, IVocabularyFactory) zope.security-4.0.3/src/zope/security/metaconfigure.py0000664000175000017500000002024712450532147024334 0ustar tseavertseaver00000000000000############################################################################# # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """ Register class directive. """ __docformat__ = 'restructuredtext' from types import ModuleType from zope.component.interfaces import IFactory from zope.component.factory import Factory from zope.component.interface import provideInterface from zope.component.zcml import utility from zope.interface import classImplements from zope.schema.interfaces import IField from zope.configuration.exceptions import ConfigurationError from zope.security.checker import Checker from zope.security.checker import CheckerPublic from zope.security.checker import defineChecker from zope.security.checker import moduleChecker from zope.security.protectclass import protectLikeUnto from zope.security.protectclass import protectName from zope.security.protectclass import protectSetAttribute PublicPermission = 'zope.Public' def dottedName(klass): if klass is None: return 'None' return klass.__module__ + '.' + klass.__name__ class ProtectionDeclarationException(Exception): """Security-protection-specific exceptions.""" pass class ClassDirective(object): def __init__(self, _context, class_): self.__id = dottedName(class_) # this would barf on a module, anyway self.__class = class_ if isinstance(self.__class, ModuleType): #pragma NO COVER raise ConfigurationError('Content class attribute must be a class') self.__context = _context def implements(self, _context, interface): for interface in interface: _context.action( discriminator = ( 'ContentDirective', self.__class, object()), callable = classImplements, args = (self.__class, interface), ) _context.action( discriminator = None, callable = provideInterface, args = (interface.__module__ + '.' + interface.getName(), interface) ) def require(self, _context, permission=None, attributes=None, interface=None, like_class=None, set_attributes=None, set_schema=None): """Require a permission to access a specific aspect""" if like_class: self.__mimic(_context, like_class) if not (interface or attributes or set_attributes or set_schema): if like_class: return raise ConfigurationError("Nothing required") if not permission: raise ConfigurationError("No permission specified") if interface: for i in interface: if i: self.__protectByInterface(i, permission) if attributes: self.__protectNames(attributes, permission) if set_attributes: self.__protectSetAttributes(set_attributes, permission) if set_schema: for s in set_schema: self.__protectSetSchema(s, permission) def __mimic(self, _context, class_): """Base security requirements on those of the given class""" _context.action( discriminator=('mimic', self.__class, object()), callable=protectLikeUnto, args=(self.__class, class_), ) def allow(self, _context, attributes=None, interface=None): """Like require, but with permission_id zope.Public""" return self.require(_context, PublicPermission, attributes, interface) def __protectByInterface(self, interface, permission_id): "Set a permission on names in an interface." for n, d in sorted(interface.namesAndDescriptions(1)): self.__protectName(n, permission_id) self.__context.action( discriminator = None, callable = provideInterface, args = (interface.__module__ + '.' + interface.getName(), interface) ) def __protectName(self, name, permission_id): "Set a permission on a particular name." self.__context.action( discriminator = ('protectName', self.__class, name), callable = protectName, args = (self.__class, name, permission_id) ) def __protectNames(self, names, permission_id): "Set a permission on a bunch of names." for name in names: self.__protectName(name, permission_id) def __protectSetAttributes(self, names, permission_id): "Set a permission on a bunch of names." for name in names: self.__context.action( discriminator = ('protectSetAttribute', self.__class, name), callable = protectSetAttribute, args = (self.__class, name, permission_id) ) def __protectSetSchema(self, schema, permission_id): "Set a permission on a bunch of names." _context = self.__context for name in sorted(schema): field = schema[name] if IField.providedBy(field) and not field.readonly: _context.action( discriminator = ('protectSetAttribute', self.__class, name), callable = protectSetAttribute, args = (self.__class, name, permission_id) ) _context.action( discriminator = None, callable = provideInterface, args = (schema.__module__ + '.' + schema.getName(), schema) ) def __call__(self): "Handle empty/simple declaration." return () def factory(self, _context, id=None, title="", description=''): """Register a zmi factory for this class""" id = id or self.__id factoryObj = Factory(self.__class, title, description) # note factories are all in one pile, utilities and content, # so addable names must also act as if they were all in the # same namespace, despite the utilities/content division utility(_context, IFactory, factoryObj, permission=PublicPermission, name=id) def protectModule(module, name, permission): """Set up a module checker to require a permission to access a name If there isn't a checker for the module, create one. """ checker = moduleChecker(module) if checker is None: checker = Checker({}, {}) defineChecker(module, checker) if permission == 'zope.Public': # Translate public permission to CheckerPublic permission = CheckerPublic # We know a dictionary get method was used because we set it protections = checker.get_permissions protections[name] = permission def _names(attributes, interfaces): seen = {} for name in attributes: if not name in seen: seen[name] = 1 yield name for interface in interfaces: for name in interface: if not name in seen: seen[name] = 1 yield name def allow(context, attributes=(), interface=()): for name in _names(attributes, interface): context.action( discriminator=('http://namespaces.zope.org/zope:module', context.module, name), callable = protectModule, args = (context.module, name, 'zope.Public'), ) def require(context, permission, attributes=(), interface=()): for name in _names(attributes, interface): context.action( discriminator=('http://namespaces.zope.org/zope:module', context.module, name), callable = protectModule, args = (context.module, name, permission), ) zope.security-4.0.3/src/zope/security/i18n.py0000664000175000017500000000157212450532147022263 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2003 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Customization of zope.i18n for the Zope application server """ __docformat__ = 'restructuredtext' # import this as _ to create i18n messages in the zope domain from zope.i18nmessageid import MessageFactory ZopeMessageFactory = MessageFactory('zope') zope.security-4.0.3/src/zope/security/decorator.py0000664000175000017500000000605512450532147023467 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2003 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Decorator support Decorators are proxies that are mostly transparent but that may provide additional features. """ from zope.proxy import getProxiedObject from zope.proxy import ProxyBase from zope.proxy.decorator import SpecificationDecoratorBase from zope.security.checker import CombinedChecker from zope.security.checker import selectChecker from zope.security.proxy import Proxy from zope.security.proxy import getChecker class DecoratedSecurityCheckerDescriptor(object): """Descriptor for a Decorator that provides a decorated security checker. """ def __get__(self, inst, cls=None): if inst is None: return self else: proxied_object = getProxiedObject(inst) if type(proxied_object) is Proxy: checker = getChecker(proxied_object) else: checker = getattr(proxied_object, '__Security_checker__', None) if checker is None: checker = selectChecker(proxied_object) wrapper_checker = selectChecker(inst) if wrapper_checker is None and checker is None: raise AttributeError("%r has no attribute %r" % (proxied_object.__class__.__name__, '__Security_checker__')) elif wrapper_checker is None: return checker elif checker is None: return wrapper_checker else: return CombinedChecker(wrapper_checker, checker) def __set__(self, inst, value): raise TypeError("Can't set __Security_checker__ on a decorated object") class SecurityCheckerDecoratorBase(ProxyBase): """Base class for a proxy that provides additional security declarations.""" __Security_checker__ = DecoratedSecurityCheckerDescriptor() class DecoratorBase(SpecificationDecoratorBase, SecurityCheckerDecoratorBase): """Base class for a proxy that provides both additional interfaces and security declarations.""" # zope.location was made independent of security. To work together with # security, we re-inject the DecoratedSecurityCheckerDescriptor onto the # location proxy from here. # This is the only sane place we found for doing it: it kicks in as soon # as someone starts using security proxies. import zope.location.location zope.location.location.LocationProxy.__Security_checker__ = ( DecoratedSecurityCheckerDescriptor()) zope.security-4.0.3/src/zope/security/zcml.py0000664000175000017500000000764512450532147022460 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2004 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Security related configuration fields. """ __docformat__ = 'restructuredtext' from zope.configuration.fields import GlobalObject from zope.configuration.fields import MessageID from zope.interface import Interface from zope.interface import implementer from zope.schema import Id from zope.schema.interfaces import IFromUnicode from zope.security.permission import checkPermission from zope.security.management import setSecurityPolicy from zope.security._compat import _u @implementer(IFromUnicode) class Permission(Id): r"""This field describes a permission. """ def fromUnicode(self, u): u = super(Permission, self).fromUnicode(u) map = getattr(self.context, 'permission_mapping', {}) return map.get(u, u) def _validate(self, value): super(Permission, self)._validate(value) if value != 'zope.Public': self.context.action( discriminator = None, callable = checkPermission, args = (None, value), # Delay execution till end. This is an # optimization. We don't want to intersperse utility # lookup, done when checking permissions, with utility # definitions. Utility lookup is expensive after # utility definition, as extensive caches have to be # rebuilt. order=9999999, ) class ISecurityPolicyDirective(Interface): """Defines the security policy that will be used for Zope.""" component = GlobalObject( title=_u("Component"), description=_u("Pointer to the object that will handle the security."), required=True) def securityPolicy(_context, component): _context.action( discriminator = 'defaultPolicy', callable = setSecurityPolicy, args = (component,) ) class IPermissionDirective(Interface): """Define a new security object.""" id = Id( title=_u("Id"), description=_u("Id as which this object will be known and used."), required=True) title = MessageID( title=_u("Title"), description=_u("Provides a title for the object."), required=True) description = MessageID( title=_u("Description"), description=_u("Provides a description for the object."), required=False) def permission(_context, id, title, description=''): from zope.security.interfaces import IPermission from zope.security.permission import Permission from zope.component.zcml import utility permission = Permission(id, title, description) utility(_context, IPermission, permission, name=id) class IRedefinePermission(Interface): """Define a permission to replace another permission.""" from_ = Permission( title=_u("Original permission"), description=_u("Original permission id to redefine."), required=True) to = Permission( title=_u("Substituted permission"), description=_u("Substituted permission id."), required=True) def redefinePermission(_context, from_, to): _context = _context.context # check if context has any permission mappings yet if not hasattr(_context, 'permission_mapping'): _context.permission_mapping={} _context.permission_mapping[from_] = to zope.security-4.0.3/src/zope/security/protectclass.py0000664000175000017500000000654712450532147024221 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Make assertions about permissions needed to access instance attributes """ from zope.security.checker import Checker from zope.security.checker import CheckerPublic from zope.security.checker import defineChecker from zope.security.checker import getCheckerForInstancesOf def protectName(class_, name, permission): """Set a permission on a particular name.""" checker = getCheckerForInstancesOf(class_) if checker is None: checker = Checker({}, {}) defineChecker(class_, checker) if permission == 'zope.Public': # Translate public permission to CheckerPublic permission = CheckerPublic # We know a dictionary was used because we set it protections = checker.get_permissions protections[name] = permission def protectSetAttribute(class_, name, permission): """Set a permission on a particular name.""" checker = getCheckerForInstancesOf(class_) if checker is None: checker = Checker({}, {}) defineChecker(class_, checker) if permission == 'zope.Public': # Translate public permission to CheckerPublic permission = CheckerPublic # We know a dictionary was used because we set it # Note however, that if a checker was created manually # and the caller used say NamesChecker or MultiChecker, # then set_permissions may be None here as Checker # defaults a missing set_permissions parameter to None. # Jim says this doensn't happens with the C version of the # checkers because they use a 'shared dummy dict'. protections = checker.set_permissions protections[name] = permission def protectLikeUnto(class_, like_unto): """Use the protections from like_unto for the given class.""" unto_checker = getCheckerForInstancesOf(like_unto) if unto_checker is None: return # We know a dictionary was used because we set it # Note however, that if a checker was created manually # and the caller used say NamesChecker or MultiChecker, # then set_permissions may be None here as Checker # defaults a missing set_permissions parameter to None. # Jim says this doensn't happens with the C version of the # checkers because they use a 'shared dummy dict'. unto_get_protections = unto_checker.get_permissions unto_set_protections = unto_checker.set_permissions checker = getCheckerForInstancesOf(class_) if checker is None: checker = Checker({}, {}) defineChecker(class_, checker) get_protections = checker.get_permissions for name in unto_get_protections: get_protections[name] = unto_get_protections[name] set_protections = checker.set_permissions for name in unto_set_protections: set_protections[name] = unto_set_protections[name] zope.security-4.0.3/src/zope/security/interfaces.py0000664000175000017500000002263012450532147023625 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2004 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Interfaces for security machinery. """ from zope.interface import Interface, Attribute, implementer from zope.interface.common.interfaces import IException, IAttributeError from zope.schema import Text, TextLine from zope.security.i18n import ZopeMessageFactory as _ class IUnauthorized(IException): pass @implementer(IUnauthorized) class Unauthorized(Exception): """Some user wasn't allowed to access a resource""" class IForbidden(IException): pass @implementer(IForbidden) class Forbidden(Exception): """A resource cannot be accessed under any circumstances """ class IForbiddenAttribute(IForbidden, IAttributeError): pass @implementer(IForbiddenAttribute) class ForbiddenAttribute(Forbidden, AttributeError): """An attribute is unavailable because it is forbidden (private) """ class ISecurityManagement(Interface): """Public security management API.""" def getSecurityPolicy(): """Get the system default security policy.""" def setSecurityPolicy(aSecurityPolicy): """Set the system default security policy. This method should only be called by system startup code. It should never, for example, be called during a web request. """ class ISecurityChecking(Interface): """Public security API.""" def checkPermission(permission, object, interaction=None): """Return whether security policy allows permission on object. 'permission' is permission name. 'object' is the object being accessed according to the permission. 'interaction' is an interaction, providing access to information such as authenticated principals. If it is None, the current interaction is used. """ class ISecurityProxyFactory(Interface): def __call__(object, checker=None): """Create a security proxy If a checker is given, then use it, otherwise, try to figure out a checker. If the object is already a security proxy, then it will be returned. """ class IChecker(Interface): """Security-proxy plugin objects that implement low-level checks The checker is responsible for creating proxies for operation return values, via the proxy method. There are check_getattr() and check_setattr() methods for checking getattr and setattr, and a check() method for all other operations. The check methods may raise errors. They return no value. Example (for __getitem__): checker.check(ob, \"__getitem__\") return checker.proxy(ob[key]) """ def check_getattr(ob, name): """Check whether attribute access is allowed. May raise Unauthorized or Forbidden. Returns no value. If a checker implements __setitem__, then __setitem__ will be called rather than check_getattr to check whether an attribute access is allowed. This is a hack that allows significantly greater performance due to the fact that low-level operator access is much faster than method access. """ def check_setattr(ob, name): """Check whether attribute assignment is allowed. May raise Unauthorized or Forbidden. Returns no value. """ def check(ob, operation): """Check whether operation is allowed. The operation name is the Python special method name, e.g. "__getitem__". May raise Unauthorized or Forbidden. Returns no value. If a checker implements __setitem__, then __setitem__ will be called rather than check to check whether an operation is allowed. This is a hack that allows significantly greater performance due to the fact that low-level operator access is much faster than method access. """ def proxy(value): """Return a security proxy for the value. If a checker implements __getitem__, then __getitem__ will be called rather than proxy to proxy the value. This is a hack that allows significantly greater performance due to the fact that low-level operator access is much faster than method access. """ class INameBasedChecker(IChecker): """Security checker that uses permissions to check attribute access.""" def permission_id(name): """Return the permission used to check attribute access on name. This permission is used by both check and check_getattr. """ def setattr_permission_id(name): """Return the permission used to check attribute assignment on name. This permission is used by check_setattr. """ class ISecurityPolicy(Interface): def __call__(participation=None): """Creates a new interaction for a given request. If participation is not None, it is added to the new interaction. """ class IInteraction(Interface): """A representation of an interaction between some actors and the system. """ participations = Attribute("""An iterable of participations.""") def add(participation): """Add a participation.""" def remove(participation): """Remove a participation.""" def checkPermission(permission, object): """Return whether security context allows permission on object. Arguments: permission -- A permission name object -- The object being accessed according to the permission """ class IParticipation(Interface): interaction = Attribute("The interaction") principal = Attribute("The authenticated principal") class NoInteraction(Exception): """No interaction started """ class IInteractionManagement(Interface): """Interaction management API. Every thread has at most one active interaction at a time. """ def newInteraction(participation=None): """Start a new interaction. If participation is not None, it is added to the new interaction. Raises an error if the calling thread already has an interaction. """ def queryInteraction(): """Return the current interaction. Return None if there is no interaction. """ def getInteraction(): """Return the current interaction. Raise NoInteraction if there isn't a current interaction. """ def endInteraction(): """End the current interaction. Does nothing if there is no interaction. """ class IPrincipal(Interface): """Principals are security artifacts that execute actions in a security environment. The most common examples of principals include user and group objects. It is likely that IPrincipal objects will have associated views used to list principals in management interfaces. For example, a system in which other meta-data are provided for principals might extend IPrincipal and register a view for the extended interface that displays the extended information. We'll probably want to define a standard view name (e.g. 'inline_summary') for this purpose. """ id = TextLine( title=_("Id"), description=_("The unique identification of the principal."), required=True, readonly=True) title = TextLine( title=_("Title"), description=_("The title of the principal. " "This is usually used in the UI."), required=False) description = Text( title=_("Description"), description=_("A detailed description of the principal."), required=False) class IGroupAwarePrincipal(IPrincipal): """Group aware principal interface Extends IPrincipal to contain group information. """ groups = Attribute( 'An iterable of groups to which the principal directly belongs') class IGroupClosureAwarePrincipal(IGroupAwarePrincipal): allGroups = Attribute( "An iterable of the full closure of the principal's groups.") class IGroup(IPrincipal): """Group of principals """ class IMemberGetterGroup(IGroup): """a group that can get its members""" def getMembers(): """return an iterable of the members of the group""" class IMemberAwareGroup(IMemberGetterGroup): """a group that can both set and get its members.""" def setMembers(value): """set members of group to the principal ids in the iterable value""" class IPermission(Interface): """A permission object.""" id = TextLine( title=_("Id"), description=_("Id as which this permission will be known and used."), readonly=True, required=True) title = TextLine( title=_("Title"), description=_("Provides a title for the permission."), required=True) description = Text( title=_("Description"), description=_("Provides a description for the permission."), required=False) zope.security-4.0.3/src/zope/security/_proxy.c0000664000175000017500000007266612450532147022632 0ustar tseavertseaver00000000000000/***************************************************************************** * * Copyright (c) 2003, 2004 Zope Foundation and Contributors. * All Rights Reserved. * * This software is subject to the provisions of the Zope Public License, * Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED * WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS * FOR A PARTICULAR PURPOSE. * ****************************************************************************** Security Proxy Implementation */ #include #include "zope/proxy/proxy.h" static PyObject *__class__str = 0, *__name__str = 0, *__module__str = 0; // Compatibility with Python 2 #if PY_MAJOR_VERSION < 3 #define IS_STRING PyString_Check #define MAKE_STRING(name) PyString_AS_STRING(name) #define FROM_STRING PyString_FromString #define FROM_STRING_FORMAT PyString_FromFormat #define INTERN PyString_InternFromString #define MOD_ERROR_VAL #define MOD_SUCCESS_VAL(val) #define MOD_INIT(name) void init##name(void) #define MOD_DEF(ob, name, doc, methods) \ ob = Py_InitModule3(name, methods, doc); #else #define PyInt_FromLong PyLong_FromLong #define IS_STRING PyUnicode_Check #define MAKE_STRING(name) PyBytes_AS_STRING( \ PyUnicode_AsUTF8String(name)) #define FROM_STRING PyUnicode_FromString #define FROM_STRING_FORMAT PyUnicode_FromFormat #define INTERN PyUnicode_InternFromString #define MOD_ERROR_VAL NULL #define MOD_SUCCESS_VAL(val) val #define MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void) #define MOD_DEF(ob, name, doc, methods) \ static struct PyModuleDef moduledef = { \ PyModuleDef_HEAD_INIT, name, doc, -1, methods, }; \ ob = PyModule_Create(&moduledef); #endif #define DECLARE_STRING(N) static PyObject *str_##N DECLARE_STRING(__3pow__); DECLARE_STRING(__call__); DECLARE_STRING(check); DECLARE_STRING(check_getattr); DECLARE_STRING(check_setattr); DECLARE_STRING(__cmp__); DECLARE_STRING(__coerce__); DECLARE_STRING(__contains__); DECLARE_STRING(__delitem__); DECLARE_STRING(__getitem__); DECLARE_STRING(__getslice__); DECLARE_STRING(__hash__); DECLARE_STRING(__iter__); DECLARE_STRING(__len__); DECLARE_STRING(next); DECLARE_STRING(__nonzero__); DECLARE_STRING(op_abs); DECLARE_STRING(op_add); DECLARE_STRING(op_and); DECLARE_STRING(op_div); DECLARE_STRING(op_divmod); DECLARE_STRING(op_float); DECLARE_STRING(op_floordiv); DECLARE_STRING(op_hex); DECLARE_STRING(op_iadd); DECLARE_STRING(op_iand); #if PY_MAJOR_VERSION < 3 DECLARE_STRING(op_idiv); #endif DECLARE_STRING(op_ifloordiv); DECLARE_STRING(op_ilshift); DECLARE_STRING(op_imod); DECLARE_STRING(op_imul); DECLARE_STRING(op_int); DECLARE_STRING(op_invert); DECLARE_STRING(op_ior); DECLARE_STRING(op_ipow); DECLARE_STRING(op_irshift); DECLARE_STRING(op_isub); DECLARE_STRING(op_itruediv); DECLARE_STRING(op_ixor); DECLARE_STRING(op_long); DECLARE_STRING(op_lshift); DECLARE_STRING(op_mod); DECLARE_STRING(op_mul); DECLARE_STRING(op_neg); DECLARE_STRING(op_oct); DECLARE_STRING(op_or); DECLARE_STRING(op_pos); DECLARE_STRING(op_radd); DECLARE_STRING(op_rand); DECLARE_STRING(op_rdiv); DECLARE_STRING(op_rdivmod); DECLARE_STRING(op_rfloordiv); DECLARE_STRING(op_rlshift); DECLARE_STRING(op_rmod); DECLARE_STRING(op_rmul); DECLARE_STRING(op_ror); DECLARE_STRING(op_rrshift); DECLARE_STRING(op_rshift); DECLARE_STRING(op_rsub); DECLARE_STRING(op_rtruediv); DECLARE_STRING(op_rxor); DECLARE_STRING(op_sub); DECLARE_STRING(op_truediv); DECLARE_STRING(op_xor); DECLARE_STRING(__pow__); DECLARE_STRING(proxy); DECLARE_STRING(__repr__); DECLARE_STRING(__rpow__); DECLARE_STRING(__setitem__); DECLARE_STRING(__setslice__); DECLARE_STRING(__str__); typedef struct { ProxyObject proxy; PyObject *proxy_checker; } SecurityProxy; #define CLEAR(O) if (O) {PyObject *t = O; O = 0; Py_DECREF(t); } #undef Proxy_Check #define Proxy_Check(proxy) \ PyObject_TypeCheck(proxy, &SecurityProxyType) static PyTypeObject SecurityProxyType; /* * Machinery to call the checker. */ static int check(SecurityProxy *self, PyObject *meth, PyObject *name) { PyObject *r; /* If the checker has __setitem__, we call it's slot rather than calling check or check_getattr. Why? Because calling operator slots is much faster than calling methods and security checks are done so often that speed matters. So we have this hack of using almost-arbitrary operations to represent methods that we call alot. */ if (self->proxy_checker->ob_type->tp_as_mapping != NULL && self->proxy_checker->ob_type->tp_as_mapping->mp_ass_subscript != NULL && meth != str_check_setattr) return self->proxy_checker->ob_type->tp_as_mapping-> mp_ass_subscript(self->proxy_checker, self->proxy.proxy_object, name); r = PyObject_CallMethodObjArgs(self->proxy_checker, meth, self->proxy.proxy_object, name, NULL); if (r == NULL) return -1; Py_DECREF(r); return 0; } /* If the checker has __getitem__, we call it's slot rather than calling proxy. Why? Because calling operator slots is much faster than calling methods and security checks are done so often that speed matters. So we have this hack of using almost-arbitrary operations to represent methods that we call alot. */ #define PROXY_RESULT(self, result) \ if (result != NULL) { \ PyObject *tmp; \ if (self->proxy_checker->ob_type->tp_as_mapping != NULL \ && self->proxy_checker->ob_type->tp_as_mapping->mp_subscript != NULL) \ tmp = self->proxy_checker->ob_type->tp_as_mapping-> \ mp_subscript(self->proxy_checker, result); \ else \ tmp = PyObject_CallMethodObjArgs(self->proxy_checker, str_proxy, \ result, NULL); \ Py_DECREF(result); \ result = tmp; \ } typedef PyObject *(*function1)(PyObject *); static PyObject * check1(SecurityProxy *self, PyObject *opname, function1 operation) { PyObject *result = NULL; if (check(self, str_check, opname) >= 0) { result = operation(self->proxy.proxy_object); PROXY_RESULT(self, result); } return result; } static PyObject * check2(PyObject *self, PyObject *other, PyObject *opname, PyObject *ropname, binaryfunc operation) { PyObject *result = NULL; if (Proxy_Check(self)) { if (check((SecurityProxy*)self, str_check, opname) >= 0) { result = operation(((SecurityProxy*)self)->proxy.proxy_object, other); PROXY_RESULT(((SecurityProxy*)self), result); } } else if (Proxy_Check(other)) { if (check((SecurityProxy*)other, str_check, ropname) >= 0) { result = operation(self, ((SecurityProxy*)other)->proxy.proxy_object); PROXY_RESULT(((SecurityProxy*)other), result); } } else { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } return result; } static PyObject * check2i(SecurityProxy *self, PyObject *other, PyObject *opname, binaryfunc operation) { PyObject *result = NULL; if (check(self, str_check, opname) >= 0) { result = operation(self->proxy.proxy_object, other); if (result == self->proxy.proxy_object) { /* If the operation was really carried out inplace, don't create a new proxy, but use the old one. */ Py_DECREF(result); Py_INCREF((PyObject *)self); result = (PyObject *)self; } else PROXY_RESULT(self, result); } return result; } #define UNOP(NAME, CALL) \ static PyObject *proxy_##NAME(PyObject *self) \ { return check1((SecurityProxy *)self, str_op_##NAME, CALL); } #define BINOP(NAME, CALL) \ static PyObject *proxy_##NAME(PyObject *self, PyObject *other) \ { return check2(self, other, str_op_##NAME, str_op_r##NAME, CALL); } #define INPLACE(NAME, CALL) \ static PyObject *proxy_i##NAME(PyObject *self, PyObject *other) \ { return check2i((SecurityProxy *)self, other, str_op_i##NAME, CALL); } /* * Slot methods. */ static PyObject * proxy_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"object", "checker", 0}; SecurityProxy *self; PyObject *object; PyObject *checker; if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO:_Proxy.__new__", kwlist, &object, &checker)) return NULL; if (checker == Py_None) { PyErr_SetString(PyExc_ValueError, "None passed as proxy checker"); return NULL; } self = (SecurityProxy *)type->tp_alloc(type, 0); if (self == NULL) return NULL; Py_INCREF(object); Py_INCREF(checker); self->proxy.proxy_object = object; self->proxy_checker = checker; return (PyObject *)self; } /* This is needed to avoid calling the base class tp_init, which we don't need. */ static int proxy_init(PyObject *self, PyObject *args, PyObject *kw) { return 0; } static int proxy_clear(SecurityProxy *self) { CLEAR(self->proxy_checker); SecurityProxyType.tp_base->tp_clear((PyObject*)self); return 0; } static void proxy_dealloc(SecurityProxy *self) { proxy_clear(self); SecurityProxyType.tp_base->tp_dealloc((PyObject*)self); } static int proxy_traverse(SecurityProxy *self, visitproc visit, void *arg) { Py_VISIT(self->proxy.proxy_object); Py_VISIT(self->proxy_checker); return 0; } static PyObject * proxy_richcompare(SecurityProxy* self, PyObject* other, int op) { PyObject *result = NULL; result = PyObject_RichCompare(self->proxy.proxy_object, other, op); if (result == Py_True || result == Py_False) return result; PROXY_RESULT(self, result); return result; } static PyObject * proxy_iter(SecurityProxy *self) { PyObject *result = NULL; if (check(self, str_check, str___iter__) >= 0) { result = PyObject_GetIter(self->proxy.proxy_object); PROXY_RESULT(self, result); } return result; } static PyObject * proxy_iternext(SecurityProxy *self) { PyObject *result = NULL; if (check(self, str_check_getattr, str_next) >= 0) { result = PyIter_Next(self->proxy.proxy_object); PROXY_RESULT(self, result); } return result; } static PyObject * proxy_getattro(SecurityProxy *self, PyObject *name) { PyObject *result = NULL; if (check(self, str_check_getattr, name) >= 0) { result = PyObject_GetAttr(self->proxy.proxy_object, name); PROXY_RESULT(self, result); } return result; } static int proxy_setattro(SecurityProxy *self, PyObject *name, PyObject *value) { if (check(self, str_check_setattr, name) >= 0) return PyObject_SetAttr(self->proxy.proxy_object, name, value); return -1; } static PyObject * default_repr(PyObject *object) { PyObject *klass, *name = 0, *module = 0, *result = 0; char *sname, *smodule; klass = PyObject_GetAttr(object, __class__str); if (klass == NULL) return NULL; name = PyObject_GetAttr(klass, __name__str); if (name == NULL) goto err; sname = MAKE_STRING(name); if (sname == NULL) goto err; module = PyObject_GetAttr(klass, __module__str); if (module != NULL) { smodule = MAKE_STRING(module); if (smodule == NULL) goto err; result = FROM_STRING_FORMAT("", smodule, sname, object); } else { PyErr_Clear(); result = FROM_STRING_FORMAT("", sname, object); } err: Py_DECREF(klass); Py_XDECREF(name); Py_XDECREF(module); return result; } static PyObject * proxy_str(SecurityProxy *self) { PyObject *result = NULL; if (check(self, str_check, str___str__) >= 0) { result = PyObject_Str(self->proxy.proxy_object); } else { PyErr_Clear(); result = default_repr(self->proxy.proxy_object); } return result; } static PyObject * proxy_repr(SecurityProxy *self) { PyObject *result = NULL; if (check(self, str_check, str___repr__) >= 0) { result = PyObject_Repr(self->proxy.proxy_object); } else { PyErr_Clear(); result = default_repr(self->proxy.proxy_object); } return result; } #if PY_MAJOR_VERSION < 3 static int proxy_compare(SecurityProxy *self, PyObject *other) { return PyObject_Compare(self->proxy.proxy_object, other); } #endif static long proxy_hash(SecurityProxy *self) { return PyObject_Hash(self->proxy.proxy_object); } static PyObject * proxy_call(SecurityProxy *self, PyObject *args, PyObject *kwds) { PyObject *result = NULL; if (check(self, str_check, str___call__) >= 0) { result = PyObject_Call(self->proxy.proxy_object, args, kwds); PROXY_RESULT(self, result); } return result; } /* * Number methods. */ #define NUMBER_METHOD(M) \ static PyObject * \ call_##M(PyObject *self) \ { \ PyNumberMethods *nb = self->ob_type->tp_as_number; \ if (nb == NULL || nb->nb_##M == NULL) { \ PyErr_SetString(PyExc_TypeError, \ "object can't be converted to " #M); \ return NULL; \ } \ return nb->nb_##M(self); \ } NUMBER_METHOD(int) NUMBER_METHOD(float) #if PY_MAJOR_VERSION < 3 NUMBER_METHOD(long) NUMBER_METHOD(oct) NUMBER_METHOD(hex) #endif static PyObject * call_ipow(PyObject *self, PyObject *other) { /* PyNumber_InPlacePower has three args. How silly. :-) */ return PyNumber_InPlacePower(self, other, Py_None); } BINOP(add, PyNumber_Add) BINOP(sub, PyNumber_Subtract) BINOP(mul, PyNumber_Multiply) #if PY_MAJOR_VERSION < 3 BINOP(div, PyNumber_Divide) #endif BINOP(mod, PyNumber_Remainder) BINOP(divmod, PyNumber_Divmod) static PyObject * proxy_pow(PyObject *self, PyObject *other, PyObject *modulus) { PyObject *result = NULL; if (Proxy_Check(self)) { if (check((SecurityProxy*)self, str_check, str___pow__) >= 0) { result = PyNumber_Power(((SecurityProxy*)self)->proxy.proxy_object, other, modulus); PROXY_RESULT(((SecurityProxy*)self), result); } } else if (Proxy_Check(other)) { if (check((SecurityProxy*)other, str_check, str___rpow__) >= 0) { result = PyNumber_Power(self, ((SecurityProxy*)other)->proxy.proxy_object, modulus); PROXY_RESULT(((SecurityProxy*)other), result); } } else if (modulus != NULL && Proxy_Check(modulus)) { if (check((SecurityProxy*)modulus, str_check, str___3pow__) >= 0) { result = PyNumber_Power(self, other, ((SecurityProxy*)modulus)->proxy.proxy_object); PROXY_RESULT(((SecurityProxy*)modulus), result); } } else { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } return result; } BINOP(lshift, PyNumber_Lshift) BINOP(rshift, PyNumber_Rshift) BINOP(and, PyNumber_And) BINOP(xor, PyNumber_Xor) BINOP(or, PyNumber_Or) #if PY_MAJOR_VERSION < 3 static int proxy_coerce(PyObject **p_self, PyObject **p_other) { PyObject *self = *p_self; PyObject *other = *p_other; assert(Proxy_Check(self)); if (check((SecurityProxy*)self, str_check, str___coerce__) >= 0) { PyObject *left = ((SecurityProxy*)self)->proxy.proxy_object; PyObject *right = other; int r; r = PyNumber_CoerceEx(&left, &right); if (r != 0) return r; /* Now left and right have been INCREF'ed. Any new value that comes out is proxied; any unchanged value is left unchanged. */ if (left == ((SecurityProxy*)self)->proxy.proxy_object) { /* Keep the old proxy */ Py_DECREF(left); Py_INCREF(self); left = self; } else { PROXY_RESULT(((SecurityProxy*)self), left); if (left == NULL) { Py_DECREF(right); return -1; } } if (right != other) { PROXY_RESULT(((SecurityProxy*)self), right); if (right == NULL) { Py_DECREF(left); return -1; } } *p_self = left; *p_other = right; return 0; } return -1; } #endif UNOP(neg, PyNumber_Negative) UNOP(pos, PyNumber_Positive) UNOP(abs, PyNumber_Absolute) static int proxy_nonzero(PyObject *self) { return PyObject_IsTrue(((SecurityProxy*)self)->proxy.proxy_object); } UNOP(invert, PyNumber_Invert) UNOP(int, call_int) UNOP(float, call_float) #if PY_MAJOR_VERSION < 3 UNOP(long, call_long) UNOP(oct, call_oct) UNOP(hex, call_hex) #endif INPLACE(add, PyNumber_InPlaceAdd) INPLACE(sub, PyNumber_InPlaceSubtract) INPLACE(mul, PyNumber_InPlaceMultiply) #if PY_MAJOR_VERSION < 3 INPLACE(div, PyNumber_InPlaceDivide) #endif INPLACE(mod, PyNumber_InPlaceRemainder) INPLACE(pow, call_ipow) INPLACE(lshift, PyNumber_InPlaceLshift) INPLACE(rshift, PyNumber_InPlaceRshift) INPLACE(and, PyNumber_InPlaceAnd) INPLACE(xor, PyNumber_InPlaceXor) INPLACE(or, PyNumber_InPlaceOr) BINOP(floordiv, PyNumber_FloorDivide) BINOP(truediv, PyNumber_TrueDivide) INPLACE(floordiv, PyNumber_InPlaceFloorDivide) INPLACE(truediv, PyNumber_InPlaceTrueDivide) /* * Sequence methods. */ static Py_ssize_t proxy_length(SecurityProxy *self) { if (check(self, str_check, str___len__) >= 0) return PyObject_Length(self->proxy.proxy_object); return -1; } /* sq_item and sq_ass_item may be called by PySequece_{Get,Set}Item(). */ static PyObject *proxy_getitem(SecurityProxy *, PyObject *); static int proxy_setitem(SecurityProxy *, PyObject *, PyObject *); static PyObject * proxy_igetitem(SecurityProxy *self, Py_ssize_t i) { PyObject *key = PyInt_FromLong(i); PyObject *res = NULL; if (key != NULL) { res = proxy_getitem(self, key); Py_DECREF(key); } return res; } static int proxy_isetitem(SecurityProxy *self, Py_ssize_t i, PyObject *value) { PyObject *key = PyInt_FromLong(i); int res = -1; if (key != NULL) { res = proxy_setitem(self, key, value); Py_DECREF(key); } return res; } static PyObject * proxy_slice(SecurityProxy *self, Py_ssize_t start, Py_ssize_t end) { PyObject *result = NULL; if (check(self, str_check, str___getslice__) >= 0) { result = PySequence_GetSlice(self->proxy.proxy_object, start, end); PROXY_RESULT(self, result); } return result; } static int proxy_ass_slice(SecurityProxy *self, Py_ssize_t i, Py_ssize_t j, PyObject *value) { if (check(self, str_check, str___setslice__) >= 0) return PySequence_SetSlice(self->proxy.proxy_object, i, j, value); return -1; } static int proxy_contains(SecurityProxy *self, PyObject *value) { if (check(self, str_check, str___contains__) >= 0) return PySequence_Contains(self->proxy.proxy_object, value); return -1; } /* * Mapping methods. */ static PyObject * proxy_getitem(SecurityProxy *self, PyObject *key) { PyObject *result = NULL; if (check(self, str_check, str___getitem__) >= 0) { result = PyObject_GetItem(self->proxy.proxy_object, key); PROXY_RESULT(self, result); } return result; } static int proxy_setitem(SecurityProxy *self, PyObject *key, PyObject *value) { if (value == NULL) { if (check(self, str_check, str___delitem__) >= 0) return PyObject_DelItem(self->proxy.proxy_object, key); } else { if (check(self, str_check, str___setitem__) >= 0) return PyObject_SetItem(self->proxy.proxy_object, key, value); } return -1; } /* * Normal methods. */ static PyNumberMethods proxy_as_number = { proxy_add, /* nb_add */ proxy_sub, /* nb_subtract */ proxy_mul, /* nb_multiply */ #if PY_MAJOR_VERSION < 3 proxy_div, /* nb_divide */ #endif proxy_mod, /* nb_remainder */ proxy_divmod, /* nb_divmod */ proxy_pow, /* nb_power */ proxy_neg, /* nb_negative */ proxy_pos, /* nb_positive */ proxy_abs, /* nb_absolute */ proxy_nonzero, /* nb_nonzero */ proxy_invert, /* nb_invert */ proxy_lshift, /* nb_lshift */ proxy_rshift, /* nb_rshift */ proxy_and, /* nb_and */ proxy_xor, /* nb_xor */ proxy_or, /* nb_or */ #if PY_MAJOR_VERSION < 3 proxy_coerce, /* nb_coerce */ #endif proxy_int, /* nb_int */ #if PY_MAJOR_VERSION < 3 proxy_long, /* nb_long */ #else 0, /* nb_reserved */ #endif proxy_float, /* nb_float */ #if PY_MAJOR_VERSION < 3 proxy_oct, /* nb_oct */ proxy_hex, /* nb_hex */ #endif /* Added in release 2.0 */ /* These require the Py_TPFLAGS_HAVE_INPLACEOPS flag */ proxy_iadd, /* nb_inplace_add */ proxy_isub, /* nb_inplace_subtract */ proxy_imul, /* nb_inplace_multiply */ #if PY_MAJOR_VERSION < 3 proxy_idiv, /* nb_inplace_divide */ #endif proxy_imod, /* nb_inplace_remainder */ (ternaryfunc)proxy_ipow, /* nb_inplace_power */ proxy_ilshift, /* nb_inplace_lshift */ proxy_irshift, /* nb_inplace_rshift */ proxy_iand, /* nb_inplace_and */ proxy_ixor, /* nb_inplace_xor */ proxy_ior, /* nb_inplace_or */ /* Added in release 2.2 */ /* These require the Py_TPFLAGS_HAVE_CLASS flag */ proxy_floordiv, /* nb_floor_divide */ proxy_truediv, /* nb_true_divide */ proxy_ifloordiv, /* nb_inplace_floor_divide */ proxy_itruediv, /* nb_inplace_true_divide */ }; static PySequenceMethods proxy_as_sequence = { (lenfunc)proxy_length, /* sq_length */ 0, /* sq_concat */ 0, /* sq_repeat */ (ssizeargfunc)proxy_igetitem, /* sq_item */ (ssizessizeargfunc)proxy_slice, /* sq_slice */ (ssizeobjargproc)proxy_isetitem, /* sq_ass_item */ (ssizessizeobjargproc)proxy_ass_slice, /* sq_ass_slice */ (objobjproc)proxy_contains, /* sq_contains */ }; static PyMappingMethods proxy_as_mapping = { (lenfunc)proxy_length, /* mp_length */ (binaryfunc)proxy_getitem, /* mp_subscript */ (objobjargproc)proxy_setitem, /* mp_ass_subscript */ }; static char proxy_doc[] = "\ Security proxy class. Constructor: _Proxy(object, checker)\n\ where 'object' is an arbitrary object, and 'checker' is an object\n\ whose signature is described by the IChecker interface.\n\ A checker should have the following methods:\n\ check(object, operation) # operation is e.g. '__add__' or '__hash__'\n\ check_getattr(object, name)\n\ check_setattr(object, name)\n\ proxy(object)\n\ The check methods should raise an exception if the operation is\n\ disallowed. The proxy method should return a proxy for the object\n\ if one is needed, otherwise the object itself.\n\ "; static PyTypeObject SecurityProxyType = { PyVarObject_HEAD_INIT(NULL, 0) "zope.security._proxy._Proxy", sizeof(SecurityProxy), 0, (destructor)proxy_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ #if PY_MAJOR_VERSION < 3 (cmpfunc)proxy_compare, /* tp_compare */ #else 0, /* tp_reserved */ #endif (reprfunc)proxy_repr, /* tp_repr */ &proxy_as_number, /* tp_as_number */ &proxy_as_sequence, /* tp_as_sequence */ &proxy_as_mapping, /* tp_as_mapping */ (hashfunc)proxy_hash, /* tp_hash */ (ternaryfunc)proxy_call, /* tp_call */ (reprfunc)proxy_str, /* tp_str */ (getattrofunc)proxy_getattro, /* tp_getattro */ (setattrofunc)proxy_setattro, /* tp_setattro */ 0, /* tp_as_buffer */ #if PY_MAJOR_VERSION < 3 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES | Py_TPFLAGS_HAVE_GC, /* tp_flags */ #else // Py_TPFLAGS_CHECKTYPES is always true in Python 3 and removed. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /* tp_flags */ #endif proxy_doc, /* tp_doc */ (traverseproc)proxy_traverse, /* tp_traverse */ 0, /* tp_clear */ (richcmpfunc)proxy_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)proxy_iter, /* tp_iter */ (iternextfunc)proxy_iternext, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ proxy_init, /* tp_init */ 0, /*PyType_GenericAlloc,*/ /* tp_alloc */ proxy_new, /* tp_new */ 0, /*_PyObject_GC_Del,*/ /* tp_free */ }; static PyObject * module_getChecker(PyObject *self, PyObject *arg) { PyObject *result; if (!Proxy_Check(arg)) { PyErr_SetString(PyExc_TypeError, "getChecker argument must be a _Proxy"); return NULL; } result = ((SecurityProxy*)arg)->proxy_checker; Py_INCREF(result); return result; } static PyObject * module_getObject(PyObject *self, PyObject *arg) { PyObject *result; if (!Proxy_Check(arg)) result = arg; else result = ((SecurityProxy*)arg)->proxy.proxy_object; Py_INCREF(result); return result; } static char module___doc__[] = "Security proxy implementation."; static PyMethodDef module_functions[] = { {"getChecker", module_getChecker, METH_O, "get checker from proxy"}, {"getObject", module_getObject, METH_O, "Get the proxied object\n\nReturn the original object if not proxied."}, {NULL} }; MOD_INIT(_proxy) { PyObject *m; MOD_DEF(m, "_proxy", module___doc__, module_functions) if (m == NULL) return MOD_ERROR_VAL; if (Proxy_Import() < 0) return MOD_ERROR_VAL; #define INIT_STRING(S) \ if((str_##S = INTERN(#S)) == NULL) return MOD_ERROR_VAL #define INIT_STRING_OP(S) \ if((str_op_##S = INTERN("__" #S "__")) == NULL) return MOD_ERROR_VAL INIT_STRING(__3pow__); INIT_STRING(__call__); INIT_STRING(check); INIT_STRING(check_getattr); INIT_STRING(check_setattr); INIT_STRING(__cmp__); INIT_STRING(__coerce__); INIT_STRING(__contains__); INIT_STRING(__delitem__); INIT_STRING(__getitem__); INIT_STRING(__getslice__); INIT_STRING(__hash__); INIT_STRING(__iter__); INIT_STRING(__len__); INIT_STRING(next); INIT_STRING(__nonzero__); INIT_STRING_OP(abs); INIT_STRING_OP(add); INIT_STRING_OP(and); INIT_STRING_OP(div); INIT_STRING_OP(divmod); INIT_STRING_OP(float); INIT_STRING_OP(floordiv); INIT_STRING_OP(hex); INIT_STRING_OP(iadd); INIT_STRING_OP(iand); #if PY_MAJOR_VERSION < 3 INIT_STRING_OP(idiv); #endif INIT_STRING_OP(ifloordiv); INIT_STRING_OP(ilshift); INIT_STRING_OP(imod); INIT_STRING_OP(imul); INIT_STRING_OP(int); INIT_STRING_OP(invert); INIT_STRING_OP(ior); INIT_STRING_OP(ipow); INIT_STRING_OP(irshift); INIT_STRING_OP(isub); INIT_STRING_OP(itruediv); INIT_STRING_OP(ixor); INIT_STRING_OP(long); INIT_STRING_OP(lshift); INIT_STRING_OP(mod); INIT_STRING_OP(mul); INIT_STRING_OP(neg); INIT_STRING_OP(oct); INIT_STRING_OP(or); INIT_STRING_OP(pos); INIT_STRING_OP(radd); INIT_STRING_OP(rand); INIT_STRING_OP(rdiv); INIT_STRING_OP(rdivmod); INIT_STRING_OP(rfloordiv); INIT_STRING_OP(rlshift); INIT_STRING_OP(rmod); INIT_STRING_OP(rmul); INIT_STRING_OP(ror); INIT_STRING_OP(rrshift); INIT_STRING_OP(rshift); INIT_STRING_OP(rsub); INIT_STRING_OP(rtruediv); INIT_STRING_OP(rxor); INIT_STRING_OP(sub); INIT_STRING_OP(truediv); INIT_STRING_OP(xor); INIT_STRING(__pow__); INIT_STRING(proxy); INIT_STRING(__repr__); INIT_STRING(__rpow__); INIT_STRING(__setitem__); INIT_STRING(__setslice__); INIT_STRING(__str__); __class__str = FROM_STRING("__class__"); if (! __class__str) return MOD_ERROR_VAL; __name__str = FROM_STRING("__name__"); if (! __name__str) return MOD_ERROR_VAL; __module__str = FROM_STRING("__module__"); if (! __module__str) return MOD_ERROR_VAL; SecurityProxyType.tp_alloc = PyType_GenericAlloc; SecurityProxyType.tp_free = PyObject_GC_Del; SecurityProxyType.tp_base = &ProxyType; if (PyType_Ready(&SecurityProxyType) < 0) return MOD_ERROR_VAL; Py_INCREF(&SecurityProxyType); PyModule_AddObject(m, "_Proxy", (PyObject *)&SecurityProxyType); return MOD_SUCCESS_VAL(m); } zope.security-4.0.3/src/zope/security/tests/0000775000175000017500000000000012533437256022276 5ustar tseavertseaver00000000000000zope.security-4.0.3/src/zope/security/tests/emptymodule.py0000664000175000017500000000154112450532147025206 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """This empty module is for containing objects used in the course of tests. (There is a problem with the way the unit tests interact with the modules being tests, so the objects can't be expected to show up in place.) """ zope.security-4.0.3/src/zope/security/tests/test_decorator.py0000664000175000017500000001354212450532147025667 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2003 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Test zope.security.decorator """ import unittest class DecoratedSecurityCheckerDescriptorTests(unittest.TestCase): def setUp(self): from zope.security.checker import _clear _clear() def tearDown(self): from zope.security.checker import _clear _clear() def _getTargetClass(self): from zope.security.decorator import DecoratedSecurityCheckerDescriptor return DecoratedSecurityCheckerDescriptor def _makeOne(self): return self._getTargetClass()() def test_neither_wrapper_nor_object_has_checker(self): from zope.proxy import ProxyBase from zope.security.checker import NoProxy from zope.security.checker import defineChecker class Foo(object): a = 'a' defineChecker(Foo, NoProxy) foo = Foo() class Wrapper(ProxyBase): b = 'b' __Security_checker__ = self._makeOne() defineChecker(Wrapper, NoProxy) wrapper = Wrapper(foo) self.assertRaises(AttributeError, getattr, wrapper, '__Security_checker__') def test_both_wrapper_and_object_have_checkers_not_security_proxied(self): from zope.proxy import ProxyBase from zope.security.checker import CombinedChecker from zope.security.checker import NamesChecker from zope.security.checker import defineChecker from zope.security.interfaces import ForbiddenAttribute class Foo(object): a = 'a' fooChecker = NamesChecker(['a']) # a is public defineChecker(Foo, fooChecker) foo = Foo() fooChecker.check(foo, 'a') # no raise self.assertRaises(ForbiddenAttribute, fooChecker.check, foo, 'b') class Wrapper(ProxyBase): b = 'b' __Security_checker__ = self._makeOne() wrapperChecker = NamesChecker(['b']) # b is public defineChecker(Wrapper, wrapperChecker) wrapper = Wrapper(foo) self.assertRaises(ForbiddenAttribute, wrapperChecker.check, foo, 'a') wrapperChecker.check(foo, 'b') # no raise checker = wrapper.__Security_checker__ self.assertTrue(isinstance(checker, CombinedChecker)) checker.check(wrapper, 'a') # no raise checker.check(wrapper, 'b') # no raise def test_only_wrapper_has_checker(self): from zope.proxy import ProxyBase from zope.security.checker import NamesChecker from zope.security.checker import NoProxy from zope.security.checker import defineChecker class Foo(object): a = 'a' foo = Foo() defineChecker(Foo, NoProxy) class Wrapper(ProxyBase): b = 'b' __Security_checker__ = self._makeOne() wrapperChecker = NamesChecker(['b']) # b is public defineChecker(Wrapper, wrapperChecker) wrapper = Wrapper(foo) self.assertTrue(wrapper.__Security_checker__ is wrapperChecker) def test_only_object_has_checker(self): from zope.proxy import ProxyBase from zope.security.checker import NamesChecker from zope.security.checker import NoProxy from zope.security.checker import defineChecker class Foo(object): a = 'a' fooChecker = NamesChecker(['a']) # a is public defineChecker(Foo, fooChecker) foo = Foo() class Wrapper(ProxyBase): b = 'b' __Security_checker__ = self._makeOne() defineChecker(Wrapper, NoProxy) wrapper = Wrapper(foo) self.assertTrue(wrapper.__Security_checker__ is fooChecker) def test_both_wrapper_and_object_have_checkers_security_proxied(self): from zope.proxy import ProxyBase from zope.security.checker import CombinedChecker from zope.security.checker import NamesChecker from zope.security.checker import defineChecker from zope.security.proxy import ProxyFactory class Foo(object): a = 'a' fooChecker = NamesChecker(['a']) # a is public defineChecker(Foo, fooChecker) foo = Foo() f_sec = ProxyFactory(foo) class Wrapper(ProxyBase): b = 'b' __Security_checker__ = self._makeOne() wrapperChecker = NamesChecker(['b']) # b is public defineChecker(Wrapper, wrapperChecker) w_sec = Wrapper(f_sec) checker = w_sec.__Security_checker__ self.assertTrue(isinstance(checker, CombinedChecker)) checker.check(w_sec, 'a') # no raise checker.check(w_sec, 'b') # no raise def test_cannot_overwrite(self): from zope.proxy import ProxyBase from zope.security.checker import NoProxy from zope.security.checker import defineChecker class Foo(object): a = 'a' defineChecker(Foo, NoProxy) foo = Foo() class Wrapper(ProxyBase): b = 'b' __Security_checker__ = self._makeOne() wrapper = Wrapper(foo) def _try(): wrapper.__Security_checker__ = None self.assertRaises(TypeError, _try) def test_suite(): return unittest.TestSuite(( unittest.makeSuite(DecoratedSecurityCheckerDescriptorTests), )) zope.security-4.0.3/src/zope/security/tests/test_management.py0000664000175000017500000001613212450532147026017 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """ Unit tests for zope.security.management """ import unittest class Test(unittest.TestCase): def setUp(self): self._cleanUp() def tearDown(self): self._cleanUp() def _cleanUp(self): from zope.security.management import _clear from zope.security.management import endInteraction _clear() endInteraction() def test_import(self): from zope.interface.verify import verifyObject from zope.security import management from zope.security.interfaces import ISecurityManagement from zope.security.interfaces import IInteractionManagement verifyObject(ISecurityManagement, management) verifyObject(IInteractionManagement, management) def test_securityPolicy(self): from zope.security.management import setSecurityPolicy from zope.security.management import getSecurityPolicy from zope.security.simplepolicies import PermissiveSecurityPolicy policy = PermissiveSecurityPolicy setSecurityPolicy(policy) self.assertTrue(getSecurityPolicy() is policy) def test_getInteraction_none_present(self): from zope.security.interfaces import NoInteraction from zope.security.management import getInteraction self.assertRaises(NoInteraction, getInteraction) def test_queryInteraction_none_present(self): from zope.security.management import queryInteraction self.assertEqual(queryInteraction(), None) def test_newInteraction(self): from zope.security.management import newInteraction from zope.security.management import queryInteraction newInteraction() interaction = queryInteraction() self.assertTrue(interaction is not None) def test_newInteraction_repeated_without_end(self): from zope.security.management import ExistingInteraction from zope.security.management import newInteraction newInteraction() self.assertRaises(ExistingInteraction, newInteraction) def test_endInteraction(self): from zope.security.management import endInteraction from zope.security.management import newInteraction from zope.security.management import queryInteraction newInteraction() endInteraction() self.assertEqual(queryInteraction(), None) def test_endInteraction_repeated(self): from zope.security.management import endInteraction from zope.security.management import newInteraction from zope.security.management import queryInteraction newInteraction() interaction = queryInteraction() endInteraction() self.assertEqual(queryInteraction(), None) endInteraction() self.assertEqual(queryInteraction(), None) def test_restoreInteraction_after_end(self): from zope.security.management import endInteraction from zope.security.management import newInteraction from zope.security.management import queryInteraction from zope.security.management import restoreInteraction newInteraction() interaction = queryInteraction() endInteraction() restoreInteraction() self.assertTrue(interaction is queryInteraction()) def test_restoreInteraction_after_new(self): from zope.security.management import newInteraction from zope.security.management import queryInteraction from zope.security.management import restoreInteraction newInteraction() self.assertTrue(queryInteraction() is not None) restoreInteraction() # restore to no interaction self.assertTrue(queryInteraction() is None) def test_restoreInteraction_after_neither(self): from zope.security.management import queryInteraction from zope.security.management import restoreInteraction from zope.security._definitions import thread_local try: del thread_local.interaction except AttributeError: pass try: del thread_local.previous_interaction except AttributeError: pass restoreInteraction() self.assertTrue(queryInteraction() is None) def test_checkPermission_w_no_interaction(self): from zope.security.management import checkPermission from zope.security.interfaces import NoInteraction permission = 'zope.Test' obj = object() self.assertRaises(NoInteraction, checkPermission, permission, obj) def test_checkPermission_w_interaction(self): from zope.security.management import checkPermission from zope.security.management import setSecurityPolicy from zope.security.management import queryInteraction from zope.security.management import newInteraction permission = 'zope.Test' obj = object() class PolicyStub(object): def checkPermission(s, p, o,): self.assertTrue(p is permission) self.assertTrue(o is obj) self.assertTrue(s is queryInteraction() or s is interaction) return s is interaction setSecurityPolicy(PolicyStub) newInteraction() interaction = queryInteraction() self.assertEqual(checkPermission(permission, obj), True) def test_checkPermission_forbidden_policy(self): from zope.security import checkPermission from zope.security.checker import CheckerPublic from zope.security.management import setSecurityPolicy from zope.security.management import newInteraction obj = object() class ForbiddenPolicyStub(object): def checkPermission(s, p, o): return False setSecurityPolicy(ForbiddenPolicyStub) newInteraction() self.assertEqual(checkPermission('zope.Test', obj), False) self.assertEqual(checkPermission(None, obj), True) self.assertEqual(checkPermission(CheckerPublic, obj), True) def test_system_user(self): from zope.security.management import system_user from zope.security._compat import TEXT from zope.security._compat import _u self.assertEqual(system_user.id, _u('zope.security.management.system_user')) self.assertEqual(system_user.title, _u('System')) for name in 'id', 'title', 'description': self.assertTrue(isinstance(getattr(system_user, name), TEXT)) def test_suite(): return unittest.TestSuite(( unittest.makeSuite(Test), )) zope.security-4.0.3/src/zope/security/tests/test_metaconfigure.py0000664000175000017500000007431612450532147026543 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2012 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Test ZCML directives """ import unittest class Test_dottedName(unittest.TestCase): def _callFUT(self, obj): from zope.security.metaconfigure import dottedName return dottedName(obj) def test_dottted_name_w_None(self): self.assertEqual(self._callFUT(None), 'None') def test_dottted_name_w_class(self): self.assertEqual(self._callFUT(Test_dottedName), 'zope.security.tests.test_metaconfigure.' + 'Test_dottedName') class ClassDirectiveTests(unittest.TestCase): def _getTargetClass(self): from zope.security.metaconfigure import ClassDirective return ClassDirective def _makeOne(self, _context, class_): return self._getTargetClass()(_context, class_) #def test_ctor_non_class(self): TODO needs better guard in __init__ def test_implements_empty(self): context = DummyZCMLContext() directive = self._makeOne(context, Foo) directive.implements(context, []) self.assertEqual(len(context._actions), 0) def test_implements_single_interface(self): from zope.component.interface import provideInterface from zope.interface import Interface from zope.interface import classImplements class IFoo(Interface): pass context = DummyZCMLContext() directive = self._makeOne(context, Foo) directive.implements(context, [IFoo]) self.assertEqual(len(context._actions), 2) self.assertEqual(context._actions[0]['discriminator'][:2], ('ContentDirective', Foo, )) #3rd is object() self.assertTrue(context._actions[0]['callable'] is classImplements) self.assertEqual(context._actions[0]['args'], (Foo, IFoo)) self.assertTrue(context._actions[1]['discriminator'] is None) self.assertTrue(context._actions[1]['callable'] is provideInterface) self.assertEqual(context._actions[1]['args'], ('zope.security.tests.test_metaconfigure.IFoo', IFoo)) def test_implements_multiple_interfaces(self): from zope.component.interface import provideInterface from zope.interface import Interface from zope.interface import classImplements class IFoo(Interface): pass class IBar(Interface): pass context = DummyZCMLContext() directive = self._makeOne(context, Foo) directive.implements(context, [IFoo, IBar]) self.assertEqual(len(context._actions), 4) self.assertEqual(context._actions[0]['discriminator'][:2], ('ContentDirective', Foo, )) #3rd is object() self.assertTrue(context._actions[0]['callable'] is classImplements) self.assertEqual(context._actions[0]['args'], (Foo, IFoo)) self.assertTrue(context._actions[1]['discriminator'] is None) self.assertTrue(context._actions[1]['callable'] is provideInterface) self.assertEqual(context._actions[1]['args'], ('zope.security.tests.test_metaconfigure.IFoo', IFoo)) self.assertEqual(context._actions[2]['discriminator'][:2], ('ContentDirective', Foo, )) #3rd is object() self.assertTrue(context._actions[2]['callable'] is classImplements) self.assertEqual(context._actions[2]['args'], (Foo, IBar)) self.assertTrue(context._actions[3]['discriminator'] is None) self.assertTrue(context._actions[3]['callable'] is provideInterface) self.assertEqual(context._actions[3]['args'], ('zope.security.tests.test_metaconfigure.IBar', IBar)) def test_require_only_like_class(self): from zope.security.protectclass import protectLikeUnto class Bar(object): pass context = DummyZCMLContext() directive = self._makeOne(context, Foo) directive.require(context, like_class=Bar) self.assertEqual(len(context._actions), 1) self.assertEqual(context._actions[0]['discriminator'][:2], ('mimic', Foo, )) #3rd is object() self.assertTrue(context._actions[0]['callable'] is protectLikeUnto) self.assertEqual(context._actions[0]['args'], (Foo, Bar)) def test_require_only_permission(self): from zope.configuration.exceptions import ConfigurationError class Bar(object): pass context = DummyZCMLContext() directive = self._makeOne(context, Foo) self.assertRaises(ConfigurationError, directive.require, context, permission='testing') def test_require_no_like_class_wo_permission(self): from zope.configuration.exceptions import ConfigurationError class Bar(object): pass context = DummyZCMLContext() directive = self._makeOne(context, Foo) self.assertRaises(ConfigurationError, directive.require, context, attributes=('foo', 'bar')) def test_require_w_single_interface(self): from zope.component.interface import provideInterface from zope.interface import Attribute from zope.interface import Interface from zope.security.protectclass import protectName class IFoo(Interface): bar = Attribute("Bar") baz = Attribute("Baz") context = DummyZCMLContext() directive = self._makeOne(context, Foo) directive.require(context, permission='testing', interface=[IFoo]) self.assertEqual(len(context._actions), 3) self.assertEqual(context._actions[0]['discriminator'], ('protectName', Foo, 'bar')) self.assertTrue(context._actions[0]['callable'] is protectName) self.assertEqual(context._actions[0]['args'], (Foo, 'bar', 'testing')) self.assertEqual(context._actions[1]['discriminator'], ('protectName', Foo, 'baz')) self.assertTrue(context._actions[1]['callable'] is protectName) self.assertEqual(context._actions[1]['args'], (Foo, 'baz', 'testing')) self.assertTrue(context._actions[2]['discriminator'] is None) self.assertTrue(context._actions[2]['callable'] is provideInterface) self.assertEqual(context._actions[2]['args'], ('zope.security.tests.test_metaconfigure.IFoo', IFoo)) def test_require_w_multiple_interfaces(self): from zope.component.interface import provideInterface from zope.interface import Attribute from zope.interface import Interface from zope.security.protectclass import protectName class IFoo(Interface): bar = Attribute("Bar") class IBar(Interface): baz = Attribute("Baz") context = DummyZCMLContext() directive = self._makeOne(context, Foo) directive.require(context, permission='testing', interface=[IFoo, IBar]) self.assertEqual(len(context._actions), 4) self.assertEqual(context._actions[0]['discriminator'], ('protectName', Foo, 'bar')) self.assertTrue(context._actions[0]['callable'] is protectName) self.assertEqual(context._actions[0]['args'], (Foo, 'bar', 'testing')) self.assertTrue(context._actions[1]['discriminator'] is None) self.assertTrue(context._actions[1]['callable'] is provideInterface) self.assertEqual(context._actions[1]['args'], ('zope.security.tests.test_metaconfigure.IFoo', IFoo)) self.assertEqual(context._actions[2]['discriminator'], ('protectName', Foo, 'baz')) self.assertTrue(context._actions[2]['callable'] is protectName) self.assertEqual(context._actions[2]['args'], (Foo, 'baz', 'testing')) self.assertTrue(context._actions[3]['discriminator'] is None) self.assertTrue(context._actions[3]['callable'] is provideInterface) self.assertEqual(context._actions[3]['args'], ('zope.security.tests.test_metaconfigure.IBar', IBar)) def test_require_w_attributes(self): from zope.security.protectclass import protectName context = DummyZCMLContext() directive = self._makeOne(context, Foo) directive.require(context, permission='testing', attributes=['bar', 'baz']) self.assertEqual(len(context._actions), 2) self.assertEqual(context._actions[0]['discriminator'], ('protectName', Foo, 'bar')) self.assertTrue(context._actions[0]['callable'] is protectName) self.assertEqual(context._actions[0]['args'], (Foo, 'bar', 'testing')) self.assertEqual(context._actions[1]['discriminator'], ('protectName', Foo, 'baz')) self.assertTrue(context._actions[1]['callable'] is protectName) self.assertEqual(context._actions[1]['args'], (Foo, 'baz', 'testing')) def test_require_w_set_attributes(self): from zope.security.protectclass import protectSetAttribute context = DummyZCMLContext() directive = self._makeOne(context, Foo) directive.require(context, permission='testing', set_attributes=['bar', 'baz']) self.assertEqual(len(context._actions), 2) self.assertEqual(context._actions[0]['discriminator'], ('protectSetAttribute', Foo, 'bar')) self.assertTrue(context._actions[0]['callable'] is protectSetAttribute) self.assertEqual(context._actions[0]['args'], (Foo, 'bar', 'testing')) self.assertEqual(context._actions[1]['discriminator'], ('protectSetAttribute', Foo, 'baz')) self.assertTrue(context._actions[1]['callable'] is protectSetAttribute) self.assertEqual(context._actions[1]['args'], (Foo, 'baz', 'testing')) def test_require_w_set_schema_normal_fields(self): from zope.component.interface import provideInterface from zope.schema import Field from zope.interface import Interface from zope.security.protectclass import protectSetAttribute from zope.security._compat import _u class IFoo(Interface): bar = Field(_u("Bar")) baz = Field(_u("Baz")) context = DummyZCMLContext() directive = self._makeOne(context, Foo) directive.require(context, permission='testing', set_schema=[IFoo]) self.assertEqual(len(context._actions), 3) self.assertEqual(context._actions[0]['discriminator'], ('protectSetAttribute', Foo, 'bar')) self.assertTrue(context._actions[0]['callable'] is protectSetAttribute) self.assertEqual(context._actions[0]['args'], (Foo, 'bar', 'testing')) self.assertEqual(context._actions[1]['discriminator'], ('protectSetAttribute', Foo, 'baz')) self.assertTrue(context._actions[1]['callable'] is protectSetAttribute) self.assertEqual(context._actions[1]['args'], (Foo, 'baz', 'testing')) self.assertTrue(context._actions[2]['discriminator'] is None) self.assertTrue(context._actions[2]['callable'] is provideInterface) self.assertEqual(context._actions[2]['args'], ('zope.security.tests.test_metaconfigure.IFoo', IFoo)) def test_require_w_set_schema_ignores_non_fields(self): from zope.component.interface import provideInterface from zope.interface import Attribute from zope.interface import Interface class IFoo(Interface): bar = Attribute("Bar") context = DummyZCMLContext() directive = self._makeOne(context, Foo) directive.require(context, permission='testing', set_schema=[IFoo]) self.assertEqual(len(context._actions), 1) self.assertTrue(context._actions[0]['discriminator'] is None) self.assertTrue(context._actions[0]['callable'] is provideInterface) self.assertEqual(context._actions[0]['args'], ('zope.security.tests.test_metaconfigure.IFoo', IFoo)) def test_require_w_set_schema_ignores_readonly_fields(self): from zope.component.interface import provideInterface from zope.schema import Field from zope.interface import Interface from zope.security._compat import _u class IFoo(Interface): bar = Field(_u("Bar"), readonly=True) context = DummyZCMLContext() directive = self._makeOne(context, Foo) directive.require(context, permission='testing', set_schema=[IFoo]) self.assertEqual(len(context._actions), 1) self.assertTrue(context._actions[0]['discriminator'] is None) self.assertTrue(context._actions[0]['callable'] is provideInterface) self.assertEqual(context._actions[0]['args'], ('zope.security.tests.test_metaconfigure.IFoo', IFoo)) def test_allow_no_attributes_or_interface(self): from zope.configuration.exceptions import ConfigurationError class Bar(object): pass context = DummyZCMLContext() directive = self._makeOne(context, Foo) self.assertRaises(ConfigurationError, directive.allow, context) def test_allow_w_single_interface(self): from zope.component.interface import provideInterface from zope.interface import Attribute from zope.interface import Interface from zope.security.protectclass import protectName class IFoo(Interface): bar = Attribute("Bar") baz = Attribute("Baz") context = DummyZCMLContext() directive = self._makeOne(context, Foo) directive.allow(context, interface=[IFoo]) self.assertEqual(len(context._actions), 3) self.assertEqual(context._actions[0]['discriminator'], ('protectName', Foo, 'bar')) self.assertTrue(context._actions[0]['callable'] is protectName) self.assertEqual(context._actions[0]['args'], (Foo, 'bar', 'zope.Public')) self.assertEqual(context._actions[1]['discriminator'], ('protectName', Foo, 'baz')) self.assertTrue(context._actions[1]['callable'] is protectName) self.assertEqual(context._actions[1]['args'], (Foo, 'baz', 'zope.Public')) self.assertTrue(context._actions[2]['discriminator'] is None) self.assertTrue(context._actions[2]['callable'] is provideInterface) self.assertEqual(context._actions[2]['args'], ('zope.security.tests.test_metaconfigure.IFoo', IFoo)) def test_allow_w_multiple_interfaces(self): from zope.component.interface import provideInterface from zope.interface import Attribute from zope.interface import Interface from zope.security.protectclass import protectName class IFoo(Interface): bar = Attribute("Bar") class IBar(Interface): baz = Attribute("Baz") context = DummyZCMLContext() directive = self._makeOne(context, Foo) directive.allow(context, interface=[IFoo, IBar]) self.assertEqual(len(context._actions), 4) self.assertEqual(context._actions[0]['discriminator'], ('protectName', Foo, 'bar')) self.assertTrue(context._actions[0]['callable'] is protectName) self.assertEqual(context._actions[0]['args'], (Foo, 'bar', 'zope.Public')) self.assertTrue(context._actions[1]['discriminator'] is None) self.assertTrue(context._actions[1]['callable'] is provideInterface) self.assertEqual(context._actions[1]['args'], ('zope.security.tests.test_metaconfigure.IFoo', IFoo)) self.assertEqual(context._actions[2]['discriminator'], ('protectName', Foo, 'baz')) self.assertTrue(context._actions[2]['callable'] is protectName) self.assertEqual(context._actions[2]['args'], (Foo, 'baz', 'zope.Public')) self.assertTrue(context._actions[3]['discriminator'] is None) self.assertTrue(context._actions[3]['callable'] is provideInterface) self.assertEqual(context._actions[3]['args'], ('zope.security.tests.test_metaconfigure.IBar', IBar)) def test_allow_w_attributes(self): from zope.security.protectclass import protectName context = DummyZCMLContext() directive = self._makeOne(context, Foo) directive.allow(context, attributes=['bar', 'baz']) self.assertEqual(len(context._actions), 2) self.assertEqual(context._actions[0]['discriminator'], ('protectName', Foo, 'bar')) self.assertTrue(context._actions[0]['callable'] is protectName) self.assertEqual(context._actions[0]['args'], (Foo, 'bar', 'zope.Public')) self.assertEqual(context._actions[1]['discriminator'], ('protectName', Foo, 'baz')) self.assertTrue(context._actions[1]['callable'] is protectName) self.assertEqual(context._actions[1]['args'], (Foo, 'baz', 'zope.Public')) def test___call__(self): context = DummyZCMLContext() directive = self._makeOne(context, Foo) self.assertEqual(directive(), ()) def test_factory_wo_explicit_id(self): from zope.component.interfaces import IFactory from zope.component.interface import provideInterface from zope.component.zcml import handler context = DummyZCMLContext() context.info = 'INFO' directive = self._makeOne(context, Foo) directive.factory(context, title='TITLE', description='DESCRIPTION') self.assertEqual(len(context._actions), 2) self.assertEqual(context._actions[0]['discriminator'], ('utility', IFactory, 'zope.security.tests.test_metaconfigure.Foo')) self.assertTrue(context._actions[0]['callable'] is handler) args = context._actions[0]['args'] self.assertEqual(args[0], 'registerUtility') factory = args[1] self.assertEqual(factory._callable, Foo) self.assertEqual(factory.title, 'TITLE') self.assertEqual(factory.description, 'DESCRIPTION') self.assertEqual(args[2], IFactory) self.assertEqual(args[3], 'zope.security.tests.test_metaconfigure.Foo') self.assertEqual(args[4], 'INFO') self.assertTrue(context._actions[1]['discriminator'] is None) self.assertTrue(context._actions[1]['callable'] is provideInterface) self.assertEqual(context._actions[1]['args'], ('', IFactory)) def test_factory_w_explicit_id(self): from zope.component.interfaces import IFactory from zope.component.interface import provideInterface from zope.component.zcml import handler context = DummyZCMLContext() context.info = 'INFO' directive = self._makeOne(context, Foo) directive.factory(context, id='test_id') self.assertEqual(len(context._actions), 2) self.assertEqual(context._actions[0]['discriminator'], ('utility', IFactory, 'test_id')) self.assertTrue(context._actions[0]['callable'] is handler) args = context._actions[0]['args'] self.assertEqual(args[0], 'registerUtility') factory = args[1] self.assertEqual(factory._callable, Foo) self.assertEqual(args[2], IFactory) self.assertEqual(args[3], 'test_id') self.assertEqual(args[4], 'INFO') self.assertTrue(context._actions[1]['discriminator'] is None) self.assertTrue(context._actions[1]['callable'] is provideInterface) self.assertEqual(context._actions[1]['args'], ('', IFactory)) class Foo(object): pass class Test_protectModule(unittest.TestCase): def setUp(self): from zope.security.checker import _clear _clear() def tearDown(self): from zope.security.checker import _clear _clear() def _callFUT(self, module, name, permission): from zope.security.metaconfigure import protectModule return protectModule(module, name, permission) def test_check_wo_existing_module_checker(self): from zope.security import tests as module from zope.security.checker import _checkers perm = object() self._callFUT(module, 'name', perm) checker = _checkers[module] self.assertTrue(checker.get_permissions['name'] is perm) def test_check_w_existing_module_checker_zope_Public(self): from zope.security import tests as module from zope.security.checker import Checker from zope.security.checker import CheckerPublic from zope.security.checker import _checkers before = _checkers[module] = Checker({'other': CheckerPublic}) self._callFUT(module, 'name', 'zope.Public') checker = _checkers[module] self.assertTrue(checker is before) self.assertTrue(checker.get_permissions['name'] is CheckerPublic) class Test_allow(unittest.TestCase): def setUp(self): from zope.security.checker import _clear _clear() def tearDown(self): from zope.security.checker import _clear _clear() def _callFUT(self, context, attributes=None, interface=None): from zope.security.metaconfigure import allow if interface is None: if attributes is None: return allow(context) return allow(context, attributes) if attributes is None: return allow(context, interface=interface) return allow(context, attributes, interface) def test_empty(self): context = DummyZCMLContext() self._callFUT(context) self.assertEqual(len(context._actions), 0) def test_w_attributes(self): from zope.security.metaconfigure import protectModule ATTRS = ['foo', 'bar'] context = DummyZCMLContext() context.module = 'testing' self._callFUT(context, ATTRS) self.assertEqual(len(context._actions), len(ATTRS)) self.assertEqual(context._actions[0]['discriminator'], ('http://namespaces.zope.org/zope:module', 'testing', 'foo')) self.assertTrue(context._actions[0]['callable'] is protectModule) self.assertEqual(context._actions[0]['args'], ('testing', 'foo', 'zope.Public')) self.assertEqual(context._actions[1]['discriminator'], ('http://namespaces.zope.org/zope:module', 'testing', 'bar')) self.assertTrue(context._actions[1]['callable'] is protectModule) self.assertEqual(context._actions[1]['args'], ('testing', 'bar', 'zope.Public')) def test_w_interface(self): from zope.interface import Attribute from zope.interface import Interface from zope.security.metaconfigure import protectModule class IFoo(Interface): bar = Attribute('Bar') context = DummyZCMLContext() context.module = 'testing' self._callFUT(context, interface=[IFoo]) self.assertEqual(len(context._actions), 1) self.assertEqual(context._actions[0]['discriminator'], ('http://namespaces.zope.org/zope:module', 'testing', 'bar')) self.assertTrue(context._actions[0]['callable'] is protectModule) self.assertEqual(context._actions[0]['args'], ('testing', 'bar', 'zope.Public')) def test_w_both(self): from zope.interface import Attribute from zope.interface import Interface from zope.security.metaconfigure import protectModule class IFoo(Interface): bar = Attribute('Bar') baz = Attribute('Baz') ATTRS = ['foo', 'bar'] context = DummyZCMLContext() context.module = 'testing' self._callFUT(context, ATTRS, [IFoo]) self.assertEqual(len(context._actions), 3) self.assertEqual(context._actions[0]['discriminator'], ('http://namespaces.zope.org/zope:module', 'testing', 'foo')) self.assertTrue(context._actions[0]['callable'] is protectModule) self.assertEqual(context._actions[0]['args'], ('testing', 'foo', 'zope.Public')) self.assertEqual(context._actions[1]['discriminator'], ('http://namespaces.zope.org/zope:module', 'testing', 'bar')) self.assertTrue(context._actions[1]['callable'] is protectModule) self.assertEqual(context._actions[1]['args'], ('testing', 'bar', 'zope.Public')) self.assertEqual(context._actions[2]['discriminator'], ('http://namespaces.zope.org/zope:module', 'testing', 'baz')) self.assertTrue(context._actions[2]['callable'] is protectModule) self.assertEqual(context._actions[2]['args'], ('testing', 'baz', 'zope.Public')) class Test_requre(unittest.TestCase): def setUp(self): from zope.security.checker import _clear _clear() def tearDown(self): from zope.security.checker import _clear _clear() def _callFUT(self, context, permission, attributes=None, interface=None): from zope.security.metaconfigure import require if interface is None: if attributes is None: return require(context, permission) return require(context, permission, attributes) if attributes is None: return require(context, permission, interface=interface) return require(context, permission, attributes, interface) def test_empty(self): context = DummyZCMLContext() context.module = 'testing' perm = object() self._callFUT(context, perm) self.assertEqual(len(context._actions), 0) def test_w_attributes(self): from zope.security.metaconfigure import protectModule ATTRS = ['foo', 'bar'] context = DummyZCMLContext() context.module = 'testing' perm = object() self._callFUT(context, perm, ATTRS) self.assertEqual(len(context._actions), len(ATTRS)) self.assertEqual(context._actions[0]['discriminator'], ('http://namespaces.zope.org/zope:module', 'testing', 'foo')) self.assertTrue(context._actions[0]['callable'] is protectModule) self.assertEqual(context._actions[0]['args'], ('testing', 'foo', perm)) self.assertEqual(context._actions[1]['discriminator'], ('http://namespaces.zope.org/zope:module', 'testing', 'bar')) self.assertTrue(context._actions[1]['callable'] is protectModule) self.assertEqual(context._actions[1]['args'], ('testing', 'bar', perm)) def test_w_interface(self): from zope.interface import Attribute from zope.interface import Interface from zope.security.metaconfigure import protectModule class IFoo(Interface): bar = Attribute('Bar') context = DummyZCMLContext() context.module = 'testing' perm = object() self._callFUT(context, perm, interface=[IFoo]) self.assertEqual(len(context._actions), 1) self.assertEqual(context._actions[0]['discriminator'], ('http://namespaces.zope.org/zope:module', 'testing', 'bar')) self.assertTrue(context._actions[0]['callable'] is protectModule) self.assertEqual(context._actions[0]['args'], ('testing', 'bar', perm)) def test_w_both(self): from zope.interface import Attribute from zope.interface import Interface from zope.security.metaconfigure import protectModule class IFoo(Interface): bar = Attribute('Bar') baz = Attribute('Baz') ATTRS = ['foo', 'bar'] context = DummyZCMLContext() context.module = 'testing' perm = object() self._callFUT(context, perm, ATTRS, [IFoo]) self.assertEqual(len(context._actions), 3) self.assertEqual(context._actions[0]['discriminator'], ('http://namespaces.zope.org/zope:module', 'testing', 'foo')) self.assertTrue(context._actions[0]['callable'] is protectModule) self.assertEqual(context._actions[0]['args'], ('testing', 'foo', perm)) self.assertEqual(context._actions[1]['discriminator'], ('http://namespaces.zope.org/zope:module', 'testing', 'bar')) self.assertTrue(context._actions[1]['callable'] is protectModule) self.assertEqual(context._actions[1]['args'], ('testing', 'bar', perm)) self.assertEqual(context._actions[2]['discriminator'], ('http://namespaces.zope.org/zope:module', 'testing', 'baz')) self.assertTrue(context._actions[2]['callable'] is protectModule) self.assertEqual(context._actions[2]['args'], ('testing', 'baz', perm)) class DummyZCMLContext(object): def __init__(self): self._actions = [] def action(self, **kw): self._actions.append(kw.copy()) def test_suite(): return unittest.TestSuite([ unittest.makeSuite(Test_dottedName), unittest.makeSuite(ClassDirectiveTests), unittest.makeSuite(Test_protectModule), unittest.makeSuite(Test_allow), unittest.makeSuite(Test_allow), ]) zope.security-4.0.3/src/zope/security/tests/__init__.py0000664000175000017500000000007512450532147024402 0ustar tseavertseaver00000000000000# # This file is necessary to make this directory a package. zope.security-4.0.3/src/zope/security/tests/test_zcml_functest.py0000664000175000017500000006076312450532147026574 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2001, 2002, 2003, 2012 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Directives Tests """ import unittest def _skip_wo_zope_configuration(testfunc): try: import zope.configuration.xmlconfig except ImportError: from functools import update_wrapper def dummy(self): pass update_wrapper(dummy, testfunc) return dummy else: return testfunc def configfile(s): from zope.security._compat import StringIO return StringIO(""" %s """ % s) class TestClassDirective(unittest.TestCase): def setUp(self): from zope.security.tests.exampleclass import ExampleClass try: del ExampleClass.__implements__ except AttributeError: pass try: from zope.component.testing import setUp except ImportError: pass else: setUp() def tearDown(self): from zope.security.tests.exampleclass import ExampleClass try: del ExampleClass.__implements__ except AttributeError: pass try: from zope.component.testing import tearDown except ImportError: pass else: tearDown() def _meta(self): from zope.configuration.xmlconfig import XMLConfig import zope.security XMLConfig('meta.zcml', zope.security)() @_skip_wo_zope_configuration def testEmptyDirective(self): from zope.configuration.xmlconfig import xmlconfig self._meta() f = configfile(""" """) xmlconfig(f) @_skip_wo_zope_configuration def testImplements(self): from zope.component.interface import queryInterface from zope.configuration.xmlconfig import xmlconfig from zope.security.tests.exampleclass import ExampleClass from zope.security.tests.exampleclass import IExample self._meta() self.assertEqual(queryInterface( "zope.security.tests.exampleclass.IExample"), None) f = configfile(""" """) xmlconfig(f) self.assertTrue(IExample.implementedBy(ExampleClass)) self.assertEqual(queryInterface( "zope.security.tests.exampleclass.IExample"), IExample) @_skip_wo_zope_configuration def testMulImplements(self): from zope.component.interface import queryInterface from zope.configuration.xmlconfig import xmlconfig from zope.security.tests.exampleclass import ExampleClass from zope.security.tests.exampleclass import IExample from zope.security.tests.exampleclass import IExample2 self._meta() self.assertEqual(queryInterface( "zope.security.tests.exampleclass.IExample"), None) self.assertEqual(queryInterface( "zope.security.tests.exampleclass.IExample2"), None) f = configfile(""" """) xmlconfig(f) self.assertTrue(IExample.implementedBy(ExampleClass)) self.assertTrue(IExample2.implementedBy(ExampleClass)) self.assertEqual(queryInterface( "zope.security.tests.exampleclass.IExample"), IExample) self.assertEqual(queryInterface( "zope.security.tests.exampleclass.IExample2"), IExample2) @_skip_wo_zope_configuration def testRequire(self): from zope.configuration.xmlconfig import xmlconfig self._meta() f = configfile(""" """) xmlconfig(f) @_skip_wo_zope_configuration def testAllow(self): from zope.configuration.xmlconfig import xmlconfig self._meta() f = configfile(""" """) xmlconfig(f) @_skip_wo_zope_configuration def testMimic(self): from zope.configuration.xmlconfig import xmlconfig self._meta() f = configfile(""" """) xmlconfig(f) class TestFactorySubdirective(unittest.TestCase): def setUp(self): try: from zope.component.testing import setUp except ImportError: pass else: setUp() def tearDown(self): try: from zope.component.testing import tearDown except ImportError: pass else: tearDown() def _meta(self): from zope.configuration.xmlconfig import XMLConfig import zope.security XMLConfig('meta.zcml', zope.security)() @_skip_wo_zope_configuration def testFactory(self): from zope.component import getUtility from zope.component.interfaces import IFactory from zope.configuration.xmlconfig import xmlconfig self._meta() f = configfile(""" """) xmlconfig(f) factory = getUtility(IFactory, 'test.Example') self.assertEqual(factory.title, "Example content") self.assertEqual(factory.description, "Example description") @_skip_wo_zope_configuration def testFactoryNoId(self): from zope.component import getUtility from zope.component.interfaces import IFactory from zope.component.interfaces import ComponentLookupError from zope.configuration.xmlconfig import xmlconfig self._meta() f = configfile(""" """) xmlconfig(f) self.assertRaises(ComponentLookupError, getUtility, IFactory, 'Example') factory = getUtility( IFactory, 'zope.security.tests.exampleclass.ExampleClass') self.assertEqual(factory.title, "Example content") self.assertEqual(factory.description, "Example description") @_skip_wo_zope_configuration def testFactoryPublicPermission(self): from zope.component import getUtility from zope.component.interfaces import IFactory from zope.configuration.xmlconfig import xmlconfig self._meta() f = configfile(""" """) xmlconfig(f) factory = getUtility(IFactory, 'test.Example') self.assertTrue(hasattr(factory, '__Security_checker__')) class Context(object): actions = () def action(self, discriminator, callable, args): self.actions += ((discriminator, callable, args), ) def __repr__(self): from zope.security._compat import StringIO import re import pprint atre = re.compile(' at [0-9a-fA-Fx]+') stream = StringIO() pprinter = pprint.PrettyPrinter(stream=stream, width=60) pprinter.pprint(self.actions) r = stream.getvalue() return (''.join(atre.split(r))).strip() template = """ %s """ class TestFactoryDirective(unittest.TestCase): def setUp(self): try: from zope.component.testing import setUp except ImportError: pass else: setUp() def tearDown(self): try: from zope.component.testing import tearDown except ImportError: pass else: tearDown() def meta(self): import zope.security from zope.configuration.xmlconfig import XMLConfig XMLConfig('meta.zcml', zope.security)() @_skip_wo_zope_configuration def testFactory(self): from zope.component import createObject from zope.configuration.xmlconfig import xmlconfig from zope.security import proxy from zope.security.tests import exampleclass self.meta() f = configfile(''' ''') xmlconfig(f) obj = createObject('test.Example') self.assertTrue(proxy.isinstance(obj, exampleclass.ExampleClass)) def _pfx(name): from zope.security.tests import module return module.__name__ + '.' + name def defineDirectives(): from zope.security._compat import StringIO from zope.configuration.xmlconfig import XMLConfig from zope.configuration.xmlconfig import xmlconfig import zope.security XMLConfig('meta.zcml', zope.security)() xmlconfig(StringIO(""" """)) NOTSET = [] P1 = "zope.Extravagant" P2 = "zope.Paltry" class TestRequireDirective(unittest.TestCase): def setUp(self): from zope.interface import implementer from zope.security.tests import module try: from zope.component.testing import setUp except ImportError: pass else: setUp() defineDirectives() class B(object): def m1(self): return "m1" def m2(self): return "m2" @implementer(module.I) class C(B): def m3(self): return "m3" def m4(self): return "m4" module.test_base = B module.test_class = C module.test_instance = C() self.assertState() def tearDown(self): from zope.security.tests import module module.test_class = None try: from zope.component.testing import tearDown except ImportError: pass else: tearDown() def assertState(self, m1P=NOTSET, m2P=NOTSET, m3P=NOTSET): #Verify that class, instance, and methods have expected permissions from zope.security.checker import selectChecker from zope.security.tests import module checker = selectChecker(module.test_instance) self.assertEqual(checker.permission_id('m1'), (m1P or None)) self.assertEqual(checker.permission_id('m2'), (m2P or None)) self.assertEqual(checker.permission_id('m3'), (m3P or None)) def assertDeclaration(self, declaration, **state): from zope.security.tests import module apply_declaration(module.template_bracket % declaration) self.assertState(**state) # "testSimple*" exercises tags that do NOT have children. This mode # inherently sets the instances as well as the class attributes. @_skip_wo_zope_configuration def test_wo_any_attributes(self): from zope.configuration.exceptions import ConfigurationError from zope.security.tests import module declaration = (''' ''' % (_pfx("test_class"), P1)) self.assertRaises(ConfigurationError, apply_declaration, module.template_bracket % declaration) # "testSimple*" exercises tags that do NOT have children. This mode # inherently sets the instances as well as the class attributes. @_skip_wo_zope_configuration def testSimpleMethodsPlural(self): declaration = (''' ''' % (_pfx("test_class"), P1)) self.assertDeclaration(declaration, m1P=P1, m3P=P1) def assertSetattrState(self, m1P=NOTSET, m2P=NOTSET, m3P=NOTSET): # Verify that class, instance, and methods have expected permissions from zope.security.checker import selectChecker from zope.security.tests import module checker = selectChecker(module.test_instance) self.assertEqual(checker.setattr_permission_id('m1'), (m1P or None)) self.assertEqual(checker.setattr_permission_id('m2'), (m2P or None)) self.assertEqual(checker.setattr_permission_id('m3'), (m3P or None)) def assertSetattrDeclaration(self, declaration, **state): self.assertSetattrState(**state) @_skip_wo_zope_configuration def test_set_attributes(self): from zope.security.checker import selectChecker from zope.security.tests import module declaration = (''' ''' % (_pfx("test_class"), P1)) apply_declaration(module.template_bracket % declaration) checker = selectChecker(module.test_instance) self.assertEqual(checker.setattr_permission_id('m1'), P1) self.assertEqual(checker.setattr_permission_id('m2'), None) self.assertEqual(checker.setattr_permission_id('m3'), P1) @_skip_wo_zope_configuration def test_set_schema(self): from zope.component.interface import queryInterface from zope.security.checker import selectChecker from zope.security.tests import module self.assertEqual(queryInterface(_pfx("S")), None) declaration = (''' ''' % (_pfx("test_class"), P1, _pfx("S"))) apply_declaration(module.template_bracket % declaration) self.assertEqual(queryInterface(_pfx("S")), module.S) checker = selectChecker(module.test_instance) self.assertEqual(checker.setattr_permission_id('m1'), None) self.assertEqual(checker.setattr_permission_id('m2'), None) self.assertEqual(checker.setattr_permission_id('m3'), None) self.assertEqual(checker.setattr_permission_id('foo'), P1) self.assertEqual(checker.setattr_permission_id('bar'), P1) self.assertEqual(checker.setattr_permission_id('baro'), None) @_skip_wo_zope_configuration def test_multiple_set_schema(self): from zope.component.interface import queryInterface from zope.security.checker import selectChecker from zope.security.tests import module self.assertEqual(queryInterface(_pfx("S")), None) self.assertEqual(queryInterface(_pfx("S2")), None) declaration = (''' ''' % (_pfx("test_class"), P1, _pfx("S"), _pfx("S2"))) apply_declaration(module.template_bracket % declaration) self.assertEqual(queryInterface(_pfx("S")), module.S) self.assertEqual(queryInterface(_pfx("S2")), module.S2) checker = selectChecker(module.test_instance) self.assertEqual(checker.setattr_permission_id('m1'), None) self.assertEqual(checker.setattr_permission_id('m2'), None) self.assertEqual(checker.setattr_permission_id('m3'), None) self.assertEqual(checker.setattr_permission_id('foo'), P1) self.assertEqual(checker.setattr_permission_id('bar'), P1) self.assertEqual(checker.setattr_permission_id('foo2'), P1) self.assertEqual(checker.setattr_permission_id('bar2'), P1) self.assertEqual(checker.setattr_permission_id('baro'), None) @_skip_wo_zope_configuration def testSimpleInterface(self): from zope.component.interface import queryInterface from zope.security.tests import module self.assertEqual(queryInterface(_pfx("I")), None) declaration = (''' ''' % (_pfx("test_class"), P1, _pfx("I"))) # m1 and m2 are in the interface, so should be set, and m3 should not: self.assertDeclaration(declaration, m1P=P1, m2P=P1) # Make sure we know about the interfaces self.assertEqual(queryInterface(_pfx("I")), module.I) @_skip_wo_zope_configuration def testMultipleInterface(self): from zope.component.interface import queryInterface from zope.security.tests import module self.assertEqual(queryInterface(_pfx("I3")), None) self.assertEqual(queryInterface(_pfx("I4")), None) declaration = (''' ''' % (_pfx("test_class"), P1, _pfx("I3"), _pfx("I4"))) self.assertDeclaration(declaration, m3P=P1, m2P=P1) # Make sure we know about the interfaces self.assertEqual(queryInterface(_pfx("I3")), module.I3) self.assertEqual(queryInterface(_pfx("I4")), module.I4) # "testComposite*" exercises tags that DO have children. # "testComposite*TopPerm" exercises tags with permission in containing tag. # "testComposite*ElementPerm" exercises tags w/permission in children. @_skip_wo_zope_configuration def testCompositeNoPerm(self): # Establish rejection of declarations lacking a permission spec. from zope.configuration.xmlconfig import ZopeXMLConfigurationError declaration = (''' ''' % (_pfx("test_class"))) self.assertRaises(ZopeXMLConfigurationError, self.assertDeclaration, declaration) @_skip_wo_zope_configuration def testCompositeMethodsPluralElementPerm(self): declaration = (''' ''' % (_pfx("test_class"), P1)) self.assertDeclaration(declaration, m1P=P1, m3P=P1) @_skip_wo_zope_configuration def testCompositeInterfaceTopPerm(self): declaration = (''' ''' % (_pfx("test_class"), P1, _pfx("I"))) self.assertDeclaration(declaration, m1P=P1, m2P=P1) @_skip_wo_zope_configuration def testSubInterfaces(self): declaration = (''' ''' % (_pfx("test_class"), P1, _pfx("I2"))) # m1 and m2 are in the interface, so should be set, and m3 should not: self.assertDeclaration(declaration, m1P=P1, m2P=P1) @_skip_wo_zope_configuration def testMimicOnly(self): declaration = (''' ''' % (_pfx("test_base"), P1, _pfx("test_class"), _pfx("test_base"))) # m1 and m2 are in the interface, so should be set, and m3 should not: self.assertDeclaration(declaration, m1P=P1, m2P=P1) @_skip_wo_zope_configuration def testMimicAsDefault(self): declaration = (''' ''' % (_pfx("test_base"), P1, _pfx("test_class"), _pfx("test_base"), P2)) # m1 and m2 are in the interface, so should be set, and m3 should not: self.assertDeclaration(declaration, m1P=P1, m2P=P2, m3P=P2) def apply_declaration(declaration): '''Apply the xmlconfig machinery.''' from zope.security._compat import StringIO from zope.configuration.xmlconfig import xmlconfig return xmlconfig(StringIO(declaration)) @_skip_wo_zope_configuration def make_dummy(): from zope.interface import Interface import zope.security.zcml from zope.security._compat import _u global IDummy class IDummy(Interface): perm = zope.security.zcml.Permission(title=_u('')) perms = [] def dummy(context_, perm): global perms perms.append(perm) class DirectivesTest(unittest.TestCase): def setUp(self): try: from zope.component.testing import setUp except ImportError: pass else: setUp() def tearDown(self): del perms[:] try: from zope.component.testing import tearDown except ImportError: pass else: tearDown() @_skip_wo_zope_configuration def testRedefinePermission(self): from zope.configuration import xmlconfig from zope.security import tests make_dummy() xmlconfig.file("redefineperms.zcml", tests) self.assertEqual(perms, ['zope.Security']) def test_suite(): return unittest.TestSuite(( unittest.makeSuite(TestClassDirective), unittest.makeSuite(TestFactorySubdirective), unittest.makeSuite(TestFactoryDirective), unittest.makeSuite(TestRequireDirective), unittest.makeSuite(DirectivesTest), )) zope.security-4.0.3/src/zope/security/tests/test_testing.py0000664000175000017500000000436012450532147025360 0ustar tseavertseaver00000000000000############################################################################# # # Copyright (c) 2011 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## import unittest class InteractionHelperTest(unittest.TestCase): def tearDown(self): from zope.security.management import endInteraction endInteraction() def test_create_interaction_should_return_principal(self): from zope.security.management import getInteraction from zope.security.testing import create_interaction principal = create_interaction( 'foo', groups=['bar'], description='desc') ix = getInteraction() participation = ix.participations[0] self.assertEqual('foo', participation.principal.id) self.assertEqual(principal.groups, participation.principal.groups) self.assertEqual('desc', participation.principal.description) def test_usable_as_contextmanager(self): from zope.security.management import getInteraction from zope.security.management import queryInteraction from zope.security.testing import interaction with interaction('foo'): ix = getInteraction() participation = ix.participations[0] self.assertEqual('foo', participation.principal.id) self.assertFalse(queryInteraction()) def test_contextmanager_ends_interaction_on_exception(self): from zope.security.management import queryInteraction from zope.security.testing import interaction try: with interaction('foo'): raise RuntimeError() except RuntimeError: pass self.assertFalse(queryInteraction()) def test_suite(): return unittest.TestSuite(( unittest.makeSuite(InteractionHelperTest), )) zope.security-4.0.3/src/zope/security/tests/test_proxy.py0000664000175000017500000020643012533412673025071 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2003 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Security proxy tests """ import unittest import sys from zope.security._compat import PYTHON2, PYPY, PURE_PYTHON def _skip_if_not_Py2(testfunc): from functools import update_wrapper if not PYTHON2: def dummy(self): pass update_wrapper(dummy, testfunc) return dummy return testfunc def _skip_if_Py2(testfunc): from functools import update_wrapper if PYTHON2: def dummy(self): pass update_wrapper(dummy, testfunc) return dummy return testfunc def _skip_if_pypy250(testfunc): from functools import update_wrapper if PYPY and sys.pypy_version_info[:3] == (2,5,0): def dummy(self): pass update_wrapper(dummy, testfunc) return dummy return testfunc class ProxyTestBase(object): def _makeOne(self, object, checker): return self._getTargetClass()(object, checker) def test_ctor_w_checker_None(self): self.assertRaises(ValueError, self._makeOne, object(), None) def test___getattr___w_checker_ok(self): class Foo(object): bar = 'Bar' target = Foo() checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(proxy.bar, 'Bar') self.assertEqual(checker._checked, 'bar') self.assertEqual(checker._proxied, 'Bar') def test___getattr___w_checker_unauthorized(self): from zope.security.interfaces import Unauthorized class Foo(object): bar = 'Bar' target = Foo() checker = DummyChecker(Unauthorized) proxy = self._makeOne(target, checker) self.assertRaises(Unauthorized, getattr, proxy, 'bar') self.assertEqual(checker._checked, 'bar') def test___getattr___w_checker_forbidden_attribute(self): from zope.security.interfaces import ForbiddenAttribute class Foo(object): bar = 'Bar' target = Foo() checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, getattr, proxy, 'bar') self.assertEqual(checker._checked, 'bar') def test___setattr___w_checker_ok(self): class Foo(object): bar = 'Bar' target = Foo() checker = DummyChecker() proxy = self._makeOne(target, checker) proxy.bar = 'Baz' self.assertEqual(target.bar, 'Baz') self.assertEqual(checker._checked, 'bar') self.assertEqual(checker._proxied, None) def test___setattr___w_checker_unauthorized(self): from zope.security.interfaces import Unauthorized class Foo(object): bar = 'Bar' target = Foo() checker = DummyChecker(Unauthorized) proxy = self._makeOne(target, checker) self.assertRaises(Unauthorized, setattr, proxy, 'bar', 'Baz') self.assertEqual(checker._checked, 'bar') def test___setattr___w_checker_forbidden_attribute(self): from zope.security.interfaces import ForbiddenAttribute class Foo(object): bar = 'Bar' target = Foo() checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, setattr, proxy, 'bar', 'Baz') self.assertEqual(checker._checked, 'bar') def test___delattr___w_checker_ok(self): class Foo(object): bar = None target = Foo() target.bar = 'Bar' checker = DummyChecker() proxy = self._makeOne(target, checker) del proxy.bar self.assertEqual(target.bar, None) self.assertEqual(checker._checked, 'bar') self.assertEqual(checker._proxied, None) def test___delattr___w_checker_unauthorized(self): from zope.security.interfaces import Unauthorized class Foo(object): pass target = Foo() target.bar = 'Bar' checker = DummyChecker(Unauthorized) proxy = self._makeOne(target, checker) self.assertRaises(Unauthorized, delattr, proxy, 'bar') self.assertEqual(target.bar, 'Bar') self.assertEqual(checker._checked, 'bar') def test___delattr___w_checker_forbidden_attribute(self): from zope.security.interfaces import ForbiddenAttribute class Foo(object): pass target = Foo() target.bar = 'Bar' checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, delattr, proxy, 'bar') self.assertEqual(target.bar, 'Bar') self.assertEqual(checker._checked, 'bar') def test___str___checker_allows_str(self): target = object() checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(str(proxy), str(target)) def test___str___checker_forbids_str(self): from zope.security.interfaces import ForbiddenAttribute from zope.security._compat import _BUILTINS from zope.security.proxy import _fmt_address target = object() checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) address = _fmt_address(target) self.assertEqual(str(proxy), '' % (_BUILTINS, address)) def test___repr___checker_allows_str(self): target = object() checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(repr(proxy), repr(target)) def test___repr___checker_forbids_str(self): from zope.security.interfaces import ForbiddenAttribute from zope.security._compat import _BUILTINS from zope.security.proxy import _fmt_address target = object() checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) address = _fmt_address(target) self.assertEqual(repr(proxy), '' % (_BUILTINS, address)) @_skip_if_not_Py2 def test___cmp___w_self(self): target = object() checker = object() # checker not consulted proxy = self._makeOne(target, checker) self.assertEqual(cmp(proxy, proxy), 0) @_skip_if_not_Py2 def test___cmp___w_target(self): target = object() checker = object() # checker not consulted proxy = self._makeOne(target, checker) self.assertEqual(cmp(proxy, target), 0) @_skip_if_not_Py2 def test___cmp___w_other(self): target = object() other = object() checker = object() # checker not consulted proxy = self._makeOne(target, checker) self.assertNotEqual(cmp(proxy, other), 0) @_skip_if_not_Py2 def test___cmp___w_other_proxy(self): target = object() other = object() checker = object() # checker not consulted proxy = self._makeOne(target, checker) o_proxy = self._makeOne(target, checker) self.assertEqual(cmp(proxy, o_proxy), 0) def test___hash___w_self(self): target = object() checker = object() # checker not consulted proxy = self._makeOne(target, checker) self.assertEqual(hash(proxy), hash(target)) def test___call___w_checker_ok(self): class Foo(object): def __call__(self): return 'Bar' target = Foo() checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(proxy(), 'Bar') self.assertEqual(checker._checked, '__call__') self.assertEqual(checker._proxied, 'Bar') def test___call___w_checker_unauthorized(self): from zope.security.interfaces import Unauthorized class Foo(object): def __call__(self): return 'Bar' target = Foo() checker = DummyChecker(Unauthorized, ['__name__', '__str__']) proxy = self._makeOne(target, checker) self.assertRaises(Unauthorized, proxy) self.assertEqual(checker._checked, '__call__') def test___call___w_checker_forbidden_attribute(self): from zope.security.interfaces import ForbiddenAttribute class Foo(object): def __call__(self): return 'Bar' target = Foo() checker = DummyChecker(ForbiddenAttribute, ['__str__']) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, proxy) self.assertEqual(checker._checked, '__call__') def test___int___w_checker_allows(self): target = 3.0 checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(int(proxy), int(target)) self.assertEqual(checker._checked, '__int__') def test___int___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 3.0 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, int, proxy) self.assertEqual(checker._checked, '__int__') def test___float___w_checker_allows(self): target = 3 checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(float(proxy), float(target)) self.assertEqual(checker._checked, '__float__') def test___float___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 3 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, float, proxy) self.assertEqual(checker._checked, '__float__') @_skip_if_not_Py2 def test___long___w_checker_allows(self): target = 3.0 checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(long(proxy), long(target)) self.assertEqual(checker._checked, '__long__') @_skip_if_not_Py2 def test___long___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 3 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, long, proxy) self.assertEqual(checker._checked, '__long__') @_skip_if_not_Py2 def test___oct___w_checker_allows(self): target = 3 checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(oct(proxy), oct(target)) self.assertEqual(checker._checked, '__oct__') @_skip_if_not_Py2 def test___oct___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 3 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, oct, proxy) self.assertEqual(checker._checked, '__oct__') @_skip_if_not_Py2 def test___hex___w_checker_allows(self): target = 3 checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(hex(proxy), hex(target)) self.assertEqual(checker._checked, '__hex__') @_skip_if_not_Py2 def test___hex___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 3 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, hex, proxy) self.assertEqual(checker._checked, '__hex__') def test___add___w_checker_allows(self): target = 3 checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(proxy + 2, target + 2) self.assertEqual(checker._checked, '__add__') def test___add___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 3 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, lambda: proxy + 2) self.assertEqual(checker._checked, '__add__') def test___sub___w_checker_allows(self): target = 3 checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(proxy - 2, target - 2) self.assertEqual(checker._checked, '__sub__') def test___sub___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 3 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, lambda: proxy - 2) self.assertEqual(checker._checked, '__sub__') def test___mul___w_checker_allows(self): target = 3 checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(proxy * 2, target * 2) self.assertEqual(checker._checked, '__mul__') def test___mul___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 3 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, lambda: proxy * 2) self.assertEqual(checker._checked, '__mul__') @_skip_if_not_Py2 def test___div___w_checker_allows(self): target = 3 checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(proxy / 2, target / 2) self.assertEqual(checker._checked, '__div__') @_skip_if_not_Py2 def test___div___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 3 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, lambda: proxy / 2) self.assertEqual(checker._checked, '__div__') @_skip_if_Py2 def test___truediv___w_checker_allows(self): target = 3.0 checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(proxy / 2, target / 2) self.assertEqual(checker._checked, '__truediv__') @_skip_if_Py2 def test___truediv___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 3.0 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, lambda: proxy / 2) self.assertEqual(checker._checked, '__truediv__') def test___floordiv___w_checker_allows(self): target = 3 checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(proxy // 2, target // 2) self.assertEqual(checker._checked, '__floordiv__') def test___floordiv___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 3 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, lambda: proxy // 2) self.assertEqual(checker._checked, '__floordiv__') def test___mod___w_checker_allows(self): target = 3 checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(proxy % 2, target % 2) self.assertEqual(checker._checked, '__mod__') def test___mod___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 3 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, lambda: proxy % 2) self.assertEqual(checker._checked, '__mod__') def test___divmod___w_checker_allows(self): target = 3 checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(divmod(proxy, 2), divmod(target, 2)) self.assertEqual(checker._checked, '__divmod__') def test___divmod___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 3 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, lambda: divmod(proxy, 2)) self.assertEqual(checker._checked, '__divmod__') def test___pow___w_x_proxied_allowed(self): x, y, z = 3, 4, 7 checker = DummyChecker() proxy = self._makeOne(x, checker) self.assertEqual(pow(proxy, y, z), pow(x, y, z)) self.assertEqual(checker._checked, '__pow__') def test___pow___w_x_proxied_forbidden(self): from zope.security.interfaces import ForbiddenAttribute x, y, z = 3, 4, 7 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(y, checker) self.assertRaises(ForbiddenAttribute, lambda: pow(proxy, y, z)) self.assertEqual(checker._checked, '__pow__') def test___pow___w_y_proxied_allowed(self): x, y = 3, 4 checker = DummyChecker() proxy = self._makeOne(y, checker) self.assertEqual(pow(x, proxy), pow(x, y)) self.assertEqual(checker._checked, '__rpow__') def test___pow___w_y_proxied_forbidden(self): from zope.security.interfaces import ForbiddenAttribute x, y = 3, 4 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(y, checker) self.assertRaises(ForbiddenAttribute, lambda: pow(x, proxy)) self.assertEqual(checker._checked, '__rpow__') def test___pow___w_z_proxied_allowed(self): x, y, z = 3, 4, 7 checker = DummyChecker() proxy = self._makeOne(z, checker) self.assertEqual(pow(x, y, proxy), pow(x, y, z)) self.assertEqual(checker._checked, '__3pow__') def test___pow___w_z_proxied_forbidden(self): from zope.security.interfaces import ForbiddenAttribute x, y, z = 3, 4, 7 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(z, checker) self.assertRaises(ForbiddenAttribute, lambda: pow(x, y, proxy)) self.assertEqual(checker._checked, '__3pow__') def test___neg___w_checker_allows(self): target = 3 checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(-proxy, -target) self.assertEqual(checker._checked, '__neg__') def test___neg___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 3 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, lambda: -proxy) self.assertEqual(checker._checked, '__neg__') def test___pos___w_checker_allows(self): target = -3 checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(+proxy, +target) self.assertEqual(checker._checked, '__pos__') def test___pos___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = -3 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, lambda: +proxy) self.assertEqual(checker._checked, '__pos__') def test___abs___w_checker_allows(self): target = -3 checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(abs(proxy), abs(target)) self.assertEqual(checker._checked, '__abs__') def test___abs___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = -3 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, abs, proxy) self.assertEqual(checker._checked, '__abs__') def test___bool___(self): target = 12 checker = object() proxy = self._makeOne(target, checker) self.assertEqual(bool(proxy), bool(target)) def test___invert___w_checker_allows(self): target = 47 checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(~proxy, ~target) self.assertEqual(checker._checked, '__invert__') def test___invert___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 47 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, lambda: ~proxy) self.assertEqual(checker._checked, '__invert__') def test___lshift___w_checker_allows(self): target = 3 checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(proxy << 2, target << 2) self.assertEqual(checker._checked, '__lshift__') def test___lshift___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 3 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, lambda: proxy << 2) self.assertEqual(checker._checked, '__lshift__') def test___rshift___w_checker_allows(self): target = 3 checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(proxy >> 2, target >> 2) self.assertEqual(checker._checked, '__rshift__') def test___rshift___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 3 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, lambda: proxy >> 2) self.assertEqual(checker._checked, '__rshift__') def test___and___w_checker_allows(self): target = 3 checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(proxy & 2, target & 2) self.assertEqual(checker._checked, '__and__') def test___and___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 3 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, lambda: proxy & 2) self.assertEqual(checker._checked, '__and__') def test___xor___w_checker_allows(self): target = 3 checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(proxy ^ 2, target ^ 2) self.assertEqual(checker._checked, '__xor__') def test___xor___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 3 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, lambda: proxy ^ 2) self.assertEqual(checker._checked, '__xor__') def test___or___w_checker_allows(self): target = 3 checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(proxy | 2, target | 2) self.assertEqual(checker._checked, '__or__') def test___or___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 3 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, lambda: proxy | 2) self.assertEqual(checker._checked, '__or__') @_skip_if_not_Py2 def test___coerce___w_checker_allows(self): target = 3 checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(coerce(proxy, 4.0), coerce(target, 4.0)) self.assertEqual(checker._checked, '__coerce__') @_skip_if_not_Py2 def test___coerce___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 3 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, coerce, proxy, 4.0) self.assertEqual(checker._checked, '__coerce__') def test___iadd___not_inplace_checker_allows(self): target = 3 checker = DummyChecker() proxy = before = self._makeOne(target, checker) proxy += 3 self.assertFalse(proxy is before) self.assertEqual(proxy, 6) self.assertEqual(checker._checked, '__iadd__') def test___iadd___inplace_checker_allows(self): class Foo(object): def __init__(self, value): self.value = value def __iadd__(self, rhs): self.value += rhs return self target = Foo(3) checker = DummyChecker() proxy = before = self._makeOne(target, checker) proxy += 3 self.assertTrue(proxy is before) self.assertEqual(target.value, 6) self.assertEqual(checker._checked, '__iadd__') def test___iadd___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 3 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) try: proxy += 3 except ForbiddenAttribute: pass else: self.fail() self.assertEqual(checker._checked, '__iadd__') def test___isub___not_inplace_checker_allows(self): target = 3 checker = DummyChecker() proxy = before = self._makeOne(target, checker) proxy -= 3 self.assertFalse(proxy is before) self.assertEqual(proxy, 0) self.assertEqual(checker._checked, '__isub__') def test___isub___inplace_checker_allows(self): class Foo(object): def __init__(self, value): self.value = value def __isub__(self, rhs): self.value -= rhs return self target = Foo(3) checker = DummyChecker() proxy = before = self._makeOne(target, checker) proxy -= 3 self.assertTrue(proxy is before) self.assertEqual(target.value, 0) self.assertEqual(checker._checked, '__isub__') def test___isub___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 3 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) try: proxy -= 3 except ForbiddenAttribute: pass else: self.fail() self.assertEqual(checker._checked, '__isub__') def test___imul___not_inplace_checker_allows(self): target = 3 checker = DummyChecker() proxy = before = self._makeOne(target, checker) proxy *= 3 self.assertFalse(proxy is before) self.assertEqual(proxy, 9) self.assertEqual(checker._checked, '__imul__') def test___imul___inplace_checker_allows(self): class Foo(object): def __init__(self, value): self.value = value def __imul__(self, rhs): self.value *= rhs return self target = Foo(3) checker = DummyChecker() proxy = before = self._makeOne(target, checker) proxy *= 3 self.assertTrue(proxy is before) self.assertEqual(target.value, 9) self.assertEqual(checker._checked, '__imul__') def test___imul___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 3 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) try: proxy *= 3 except ForbiddenAttribute: pass else: self.fail() self.assertEqual(checker._checked, '__imul__') @_skip_if_not_Py2 def test___idiv___not_inplace_checker_allows(self): target = 6 checker = DummyChecker() proxy = before = self._makeOne(target, checker) proxy /= 3 self.assertFalse(proxy is before) self.assertEqual(proxy, 2) self.assertEqual(checker._checked, '__idiv__') @_skip_if_not_Py2 def test___idiv___inplace_checker_allows(self): class Foo(object): def __init__(self, value): self.value = value def __idiv__(self, rhs): self.value /= rhs return self target = Foo(6) checker = DummyChecker() proxy = before = self._makeOne(target, checker) proxy /= 3 self.assertTrue(proxy is before) self.assertEqual(target.value, 2) self.assertEqual(checker._checked, '__idiv__') @_skip_if_not_Py2 def test___idiv___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 6 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) try: proxy /= 3 except ForbiddenAttribute: pass else: self.fail() self.assertEqual(checker._checked, '__idiv__') @_skip_if_Py2 def test___itruediv___not_inplace_checker_allows(self): target = 6 checker = DummyChecker() proxy = before = self._makeOne(target, checker) proxy /= 3 self.assertFalse(proxy is before) self.assertEqual(proxy, 2) self.assertEqual(checker._checked, '__itruediv__') @_skip_if_Py2 def test___itruediv___inplace_checker_allows(self): class Foo(object): def __init__(self, value): self.value = value def __itruediv__(self, rhs): self.value /= rhs return self target = Foo(6) checker = DummyChecker() proxy = before = self._makeOne(target, checker) proxy /= 3 self.assertTrue(proxy is before) self.assertEqual(target.value, 2) self.assertEqual(checker._checked, '__itruediv__') @_skip_if_Py2 def test___itruediv___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 6 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) try: proxy /= 3 except ForbiddenAttribute: pass else: self.fail() self.assertEqual(checker._checked, '__itruediv__') def test___ifloordiv___not_inplace_checker_allows(self): target = 6 checker = DummyChecker() proxy = before = self._makeOne(target, checker) proxy //= 3 self.assertFalse(proxy is before) self.assertEqual(proxy, 2) self.assertEqual(checker._checked, '__ifloordiv__') def test___ifloordiv___inplace_checker_allows(self): class Foo(object): def __init__(self, value): self.value = value def __ifloordiv__(self, rhs): self.value //= rhs return self target = Foo(6) checker = DummyChecker() proxy = before = self._makeOne(target, checker) proxy //= 3 self.assertTrue(proxy is before) self.assertEqual(target.value, 2) self.assertEqual(checker._checked, '__ifloordiv__') def test___ifloordiv___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 6 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) try: proxy //= 3 except ForbiddenAttribute: pass else: self.fail() self.assertEqual(checker._checked, '__ifloordiv__') def test___imod___not_inplace_checker_allows(self): target = 6 checker = DummyChecker() proxy = before = self._makeOne(target, checker) proxy %= 3 self.assertFalse(proxy is before) self.assertEqual(proxy, 0) self.assertEqual(checker._checked, '__imod__') def test___imod___inplace_checker_allows(self): class Foo(object): def __init__(self, value): self.value = value def __imod__(self, rhs): self.value %= rhs return self target = Foo(6) checker = DummyChecker() proxy = before = self._makeOne(target, checker) proxy %= 3 self.assertTrue(proxy is before) self.assertEqual(target.value, 0) self.assertEqual(checker._checked, '__imod__') def test___imod___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 6 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) try: proxy %= 3 except ForbiddenAttribute: pass else: self.fail() self.assertEqual(checker._checked, '__imod__') def test___ipow___not_inplace_checker_allows(self): target = 2 checker = DummyChecker() proxy = before = self._makeOne(target, checker) proxy **= 3 self.assertFalse(proxy is before) self.assertEqual(proxy, 8) self.assertEqual(checker._checked, '__ipow__') def test___ipow___inplace_checker_allows(self): class Foo(object): def __init__(self, value): self.value = value def __ipow__(self, rhs): self.value **= rhs return self target = Foo(2) checker = DummyChecker() proxy = before = self._makeOne(target, checker) proxy **= 3 self.assertTrue(proxy is before) self.assertEqual(target.value, 8) self.assertEqual(checker._checked, '__ipow__') def test___ipow___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 2 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) try: proxy **= 3 except ForbiddenAttribute: pass else: self.fail() self.assertEqual(checker._checked, '__ipow__') def test___ilshift___not_inplace_checker_allows(self): target = 2 checker = DummyChecker() proxy = before = self._makeOne(target, checker) proxy <<= 3 self.assertFalse(proxy is before) self.assertEqual(proxy, 16) self.assertEqual(checker._checked, '__ilshift__') def test___ilshift___inplace_checker_allows(self): class Foo(object): def __init__(self, value): self.value = value def __ilshift__(self, rhs): self.value <<= rhs return self target = Foo(2) checker = DummyChecker() proxy = before = self._makeOne(target, checker) proxy <<= 3 self.assertTrue(proxy is before) self.assertEqual(target.value, 16) self.assertEqual(checker._checked, '__ilshift__') def test___ilshift___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 2 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) try: proxy <<= 3 except ForbiddenAttribute: pass else: self.fail() self.assertEqual(checker._checked, '__ilshift__') def test___irshift___not_inplace_checker_allows(self): target = 16 checker = DummyChecker() proxy = before = self._makeOne(target, checker) proxy >>= 3 self.assertFalse(proxy is before) self.assertEqual(proxy, 2) self.assertEqual(checker._checked, '__irshift__') def test___irshift___inplace_checker_allows(self): class Foo(object): def __init__(self, value): self.value = value def __irshift__(self, rhs): self.value >>= rhs return self target = Foo(16) checker = DummyChecker() proxy = before = self._makeOne(target, checker) proxy >>= 3 self.assertTrue(proxy is before) self.assertEqual(target.value, 2) self.assertEqual(checker._checked, '__irshift__') def test___irshift___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 16 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) try: proxy >>= 3 except ForbiddenAttribute: pass else: self.fail() self.assertEqual(checker._checked, '__irshift__') def test___iand___not_inplace_checker_allows(self): target = 7 checker = DummyChecker() proxy = before = self._makeOne(target, checker) proxy &= 3 self.assertFalse(proxy is before) self.assertEqual(proxy, 3) self.assertEqual(checker._checked, '__iand__') def test___iand___inplace_checker_allows(self): class Foo(object): def __init__(self, value): self.value = value def __iand__(self, rhs): self.value &= rhs return self target = Foo(7) checker = DummyChecker() proxy = before = self._makeOne(target, checker) proxy &= 3 self.assertTrue(proxy is before) self.assertEqual(target.value, 3) self.assertEqual(checker._checked, '__iand__') def test___iand___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 7 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) try: proxy &= 3 except ForbiddenAttribute: pass else: self.fail() self.assertEqual(checker._checked, '__iand__') def test___ixor___not_inplace_checker_allows(self): target = 7 checker = DummyChecker() proxy = before = self._makeOne(target, checker) proxy ^= 3 self.assertFalse(proxy is before) self.assertEqual(checker._checked, '__ixor__') self.assertEqual(proxy, 4) def test___ixor___inplace_checker_allows(self): class Foo(object): def __init__(self, value): self.value = value def __ixor__(self, rhs): self.value ^= rhs return self target = Foo(7) checker = DummyChecker() proxy = before = self._makeOne(target, checker) proxy ^= 3 self.assertTrue(proxy is before) self.assertEqual(target.value, 4) self.assertEqual(checker._checked, '__ixor__') def test___ixor___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 7 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) try: proxy ^= 3 except ForbiddenAttribute: pass else: self.fail() self.assertEqual(checker._checked, '__ixor__') def test___ior___not_inplace_checker_allows(self): target = 6 checker = DummyChecker() proxy = before = self._makeOne(target, checker) proxy |= 3 self.assertFalse(proxy is before) self.assertEqual(proxy, 7) self.assertEqual(checker._checked, '__ior__') def test___ior___inplace_checker_allows(self): class Foo(object): def __init__(self, value): self.value = value def __ior__(self, rhs): self.value |= rhs return self target = Foo(6) checker = DummyChecker() proxy = before = self._makeOne(target, checker) proxy |= 3 self.assertTrue(proxy is before) self.assertEqual(target.value, 7) self.assertEqual(checker._checked, '__ior__') def test___ior___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = 6 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) try: proxy |= 3 except ForbiddenAttribute: pass else: self.fail() self.assertEqual(checker._checked, '__ior__') def test___len___w_checker_allows(self): target = [0, 1, 2] checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(len(proxy), len(target)) self.assertEqual(checker._checked, '__len__') def test___len___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = [0, 1, 2] checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, len, proxy) self.assertEqual(checker._checked, '__len__') def test___contains___hit_w_checker_allows(self): target = [0, 1, 2] checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertTrue(1 in proxy) self.assertEqual(checker._checked, '__contains__') def test___contains___miss_w_checker_allows(self): target = [0, 1, 2] checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertFalse(4 in proxy) self.assertEqual(checker._checked, '__contains__') def test___contains___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = [0, 1, 2] checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, lambda: 0 in proxy) self.assertEqual(checker._checked, '__contains__') def test___getitem___sequence_hit_w_checker_allows(self): target = [0, 1, 2] checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(proxy[1], 1) self.assertEqual(checker._checked, '__getitem__') def test___getitem___sequence_miss_w_checker_allows(self): target = [0, 1, 2] checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertRaises(IndexError, lambda: proxy[4]) self.assertEqual(checker._checked, '__getitem__') def test___getitem___sequence_w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = [0, 1, 2] checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, lambda: proxy[0]) self.assertEqual(checker._checked, '__getitem__') def test___setitem___sequence_hit_w_checker_allows(self): target = [0, 1, 2] checker = DummyChecker() proxy = self._makeOne(target, checker) proxy[1] = 7 self.assertEqual(target[1], 7) self.assertEqual(checker._checked, '__setitem__') def test___setitem___sequence_miss_w_checker_allows(self): target = [0, 1, 2] checker = DummyChecker() proxy = self._makeOne(target, checker) def _try(): proxy[4] = 7 self.assertRaises(IndexError, _try) self.assertEqual(checker._checked, '__setitem__') def test___setitem___sequence_w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = [0, 1, 2] checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) def _try(): proxy[4] = 7 self.assertRaises(ForbiddenAttribute, _try) self.assertEqual(checker._checked, '__setitem__') @_skip_if_not_Py2 def test___getslice___w_checker_allows(self): target = [0, 1, 2] checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(proxy[1:3], [1, 2]) self.assertEqual(checker._checked, '__getslice__') @_skip_if_not_Py2 def test___getslice___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = [0, 1, 2] checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, lambda: proxy[0:2]) self.assertEqual(checker._checked, '__getslice__') @_skip_if_not_Py2 def test___setslice___w_checker_allows(self): target = [0, 1, 2] checker = DummyChecker() proxy = self._makeOne(target, checker) proxy[1:3] = [3, 4] self.assertEqual(target, [0, 3, 4]) self.assertEqual(checker._checked, '__setslice__') @_skip_if_not_Py2 def test___setslice___w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = [0, 1, 2] checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) def _try(): proxy[1:3] = [3, 4] self.assertRaises(ForbiddenAttribute, _try) self.assertEqual(checker._checked, '__setslice__') def test___getitem___mapping_hit_w_checker_allows(self): target = {'a': 0, 'b': 1, 'c': 2} checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertEqual(proxy['b'], 1) self.assertEqual(checker._checked, '__getitem__') def test___getitem___mapping_miss_w_checker_allows(self): target = {'a': 0, 'b': 1, 'c': 2} checker = DummyChecker() proxy = self._makeOne(target, checker) self.assertRaises(KeyError, lambda: proxy['d']) self.assertEqual(checker._checked, '__getitem__') def test___getitem___mapping_w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = {'a': 0, 'b': 1, 'c': 2} checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) self.assertRaises(ForbiddenAttribute, lambda: proxy['b']) self.assertEqual(checker._checked, '__getitem__') def test___setitem___mapping_hit_w_checker_allows(self): target = {'a': 0, 'b': 1, 'c': 2} checker = DummyChecker() proxy = self._makeOne(target, checker) proxy['a'] = 7 self.assertEqual(target['a'], 7) self.assertEqual(checker._checked, '__setitem__') def test___setitem___mapping_w_checker_forbids(self): from zope.security.interfaces import ForbiddenAttribute target = {'a': 0, 'b': 1, 'c': 2} checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) def _try(): proxy['a'] = 7 self.assertRaises(ForbiddenAttribute, _try) self.assertEqual(checker._checked, '__setitem__') binops = [ "x+y", "x-y", "x*y", "x/y", "divmod(x, y)", "x**y", "x//y", "x<>y", "x&y", "x|y", "x^y", ] def test_binops(self): from zope.security.proxy import removeSecurityProxy checker = DummyChecker() for expr in self.binops: first = 1 for x in [1, self._makeOne(1, checker)]: for y in [2, self._makeOne(2, checker)]: if first: z = eval(expr) first = 0 else: self.assertEqual(removeSecurityProxy(eval(expr)), z, "x=%r; y=%r; expr=%r" % (x, y, expr)) class ProxyCTests(unittest.TestCase, ProxyTestBase): def _getTargetClass(self): from zope.security.proxy import _Proxy return _Proxy class ProxyPyTests(unittest.TestCase, ProxyTestBase): def _getTargetClass(self): from zope.security.proxy import ProxyPy return ProxyPy def test_wrapper_checker_unaccessible(self): # Can't access '_wrapped' / '_checker' in C version target = object() checker = object() proxy = self._makeOne(target, checker) self.assertRaises(AttributeError, getattr, proxy, '_wrapped') self.assertRaises(AttributeError, getattr, proxy, '_checker') def test_ctor_w_checker(self): from zope.security.proxy import getObjectPy, getCheckerPy # Can't access '_wrapped' / '_checker' in C version target = object() checker = object() proxy = self._makeOne(target, checker) self.assertTrue(getObjectPy(proxy) is target) self.assertTrue(getCheckerPy(proxy) is checker) def test___delattr___w__wrapped(self): target = object() checker = object() proxy = self._makeOne(target, checker) def test(): del proxy._wrapped self.assertRaises(AttributeError, test) def test___delattr___w__checker(self): target = object() checker = object() proxy = self._makeOne(target, checker) def test(): del proxy._checker self.assertRaises(AttributeError, test) def test___pow___w_z_proxied_allowed(self): x, y, z = 3, 4, 7 checker = DummyChecker() proxy = self._makeOne(z, checker) # Disabled, because a PyProxy cannot lie about its type, so # pow(i, j, proxy(k)) will fail with a TypeError self.assertRaises(TypeError, pow, (x, y, proxy)) def test___pow___w_z_proxied_forbidden(self): from zope.security.interfaces import ForbiddenAttribute x, y, z = 3, 4, 7 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(z, checker) # Disabled, because a PyProxy cannot lie about its type, so # pow(i, j, proxy(k)) will fail with a TypeError self.assertRaises(TypeError, pow, (x, y, proxy)) def test_getObjectPy_initial_conditions(self): # Once upon a time, we dynamically set _builtin_isinstance # in z.s.proxy.isinstance itself. And at that time getObjectPy # (aka removeSecurityProxy) called z.s.proxy.isinstance if # _builtin_isinstance was not set...which recursively calls # getObjectPy. The net result was that the very first call # to getObjectPy would falsely return the proxy object if passed # a proxy, not the wrapped object! # This test makes sure we're not dynamically setting that attribute # any more. import zope.security.proxy target = object() checker = object() proxy = self._makeOne(target, checker) orig_builtin_isinstance = zope.security.proxy._builtin_isinstance zope.security.proxy._builtin_isinstance = None try: self.assertRaises(TypeError, zope.security.proxy.getObjectPy, proxy) finally: zope.security.proxy._builtin_isinstance = orig_builtin_isinstance class DummyChecker(object): _proxied = _checked = None def __init__(self, raising=None, allowed=()): self._raising = raising self._allowed = allowed def check(self, target, name): self._checked = name if name not in self._allowed: if self._raising is not None: raise self._raising(name) check_getattr = check_setattr = check def proxy(self, value): self._proxied = value return value class Test_getTestProxyItems(unittest.TestCase): def _callFUT(self, proxy): from zope.security.proxy import getTestProxyItems return getTestProxyItems(proxy) def test_w_empty_checker(self): from zope.security.checker import Checker from zope.security.proxy import Proxy target = object() proxy = Proxy(target, Checker({})) self.assertEqual(self._callFUT(proxy), []) def test_w_non_empty_checker(self): from zope.security.checker import Checker from zope.security.checker import CheckerPublic from zope.security.proxy import Proxy target = object() permission = object() proxy = Proxy(target, Checker({'foo': CheckerPublic, 'bar': permission})) self.assertEqual(self._callFUT(proxy), [('bar', permission), ('foo', CheckerPublic)]) class Test_isinstance(unittest.TestCase): def _callFUT(self, object, cls): from zope.security.proxy import isinstance return isinstance(object, cls) def test_w_unproxied_object(self): class Foo(object): pass target = Foo() self.assertTrue(self._callFUT(target, Foo)) self.assertFalse(self._callFUT(target, int)) def test_w_proxied_object(self): from zope.security.checker import Checker from zope.security.proxy import Proxy class Foo(object): pass target = Foo() proxy = Proxy(target, Checker({})) self.assertTrue(self._callFUT(proxy, Foo)) self.assertFalse(self._callFUT(proxy, int)) # pre-geddon class Checker(object): ok = 1 unproxied_types = str, def check_getattr(self, object, name): if name not in ("foo", "next", "__class__", "__name__", "__module__"): raise RuntimeError def check_setattr(self, object, name): if name != "foo": raise RuntimeError def check(self, object, opname): if not self.ok: raise RuntimeError def proxy(self, value): from zope.security.proxy import ProxyFactory if type(value) in self.unproxied_types: return value return ProxyFactory(value, self) class Something: def __init__(self): self.foo = [1,2,3] def __getitem__(self, key): return self.foo[key] def __setitem__(self, key, value): self.foo[key] = value def __delitem__(self, key): del self.foo[key] def __call__(self, arg): return 42 def __eq__(self, other): return self is other def __hash__(self): return 42 def __iter__(self): return self def __next__(self): return 42 # Infinite sequence next = __next__ def __len__(self): return 42 def __nonzero__(self): return 1 def __getslice__(self, i, j): return [42] def __setslice__(self, i, j, value): if value != [42]: raise ValueError def __contains__(self, x): return x == 42 class ProxyTests(unittest.TestCase): def setUp(self): from zope.security.proxy import ProxyFactory self.x = Something() self.c = Checker() self.p = ProxyFactory(self.x, self.c) def shouldFail(self, *args): self.c.ok = 0 self.assertRaises(RuntimeError, *args) self.c.ok = 1 def testDerivation(self): from zope.security._compat import PURE_PYTHON if PURE_PYTHON: from zope.proxy import PyProxyBase as ProxyBase else: from zope.proxy import ProxyBase self.assertTrue(isinstance(self.p, ProxyBase)) def testStr(self): from zope.security.proxy import ProxyFactory self.assertEqual(str(self.p), str(self.x)) x = Something() c = Checker() c.ok = 0 p = ProxyFactory(x, c) s = str(p) self.assertTrue(s.startswith( ">y", "x&y", "x|y", "x^y", ] def test_binops(self): from zope.security.proxy import removeSecurityProxy P = self.c.proxy for expr in self.binops: first = 1 for x in [1, P(1)]: for y in [2, P(2)]: if first: z = eval(expr) first = 0 else: self.assertEqual(removeSecurityProxy(eval(expr)), z, "x=%r; y=%r; expr=%r" % (x, y, expr)) self.shouldFail(lambda x, y: eval(expr), x, y) def test_inplace(self): # TODO: should test all inplace operators... from zope.security.proxy import removeSecurityProxy P = self.c.proxy pa = P(1) pa += 2 self.assertEqual(removeSecurityProxy(pa), 3) a = [1, 2, 3] pa = qa = P(a) pa += [4, 5, 6] self.assertTrue(pa is qa) self.assertEqual(a, [1, 2, 3, 4, 5, 6]) def doit(): pa = P(1) pa += 2 self.shouldFail(doit) pa = P(2) pa **= 2 self.assertEqual(removeSecurityProxy(pa), 4) def doit(): pa = P(2) pa **= 2 self.shouldFail(doit) @_skip_if_not_Py2 def test_coerce(self): from zope.security.proxy import removeSecurityProxy P = self.c.proxy # Before 2.3, coerce() of two proxies returns them unchanged import sys fixed_coerce = sys.version_info >= (2, 3, 0) x = P(1) y = P(2) a, b = coerce(x, y) self.assertTrue(a is x and b is y) x = P(1) y = P(2.1) a, b = coerce(x, y) self.assertTrue(removeSecurityProxy(a) == 1.0 and b is y) if fixed_coerce: self.assertTrue(type(removeSecurityProxy(a)) is float and b is y) x = P(1.1) y = P(2) a, b = coerce(x, y) self.assertTrue(a is x and removeSecurityProxy(b) == 2.0) if fixed_coerce: self.assertTrue(a is x and type(removeSecurityProxy(b)) is float) x = P(1) y = 2 a, b = coerce(x, y) self.assertTrue(a is x and b is y) x = P(1) y = 2.1 a, b = coerce(x, y) self.assertTrue(type(removeSecurityProxy(a)) is float and b is y) x = P(1.1) y = 2 a, b = coerce(x, y) self.assertTrue(a is x and type(removeSecurityProxy(b)) is float) x = 1 y = P(2) a, b = coerce(x, y) self.assertTrue(a is x and b is y) x = 1.1 y = P(2) a, b = coerce(x, y) self.assertTrue(a is x and type(removeSecurityProxy(b)) is float) x = 1 y = P(2.1) a, b = coerce(x, y) self.assertTrue(type(removeSecurityProxy(a)) is float and b is y) def test_using_mapping_slots_hack(): """The security proxy will use mapping slots, on the checker to go faster If a checker implements normally, a checkers's check and check_getattr methods are used to check operator and attribute access: >>> from zope.security.proxy import ProxyFactory >>> log = [] >>> def dump(): ... out = '\\n'.join(log) ... del log[:] ... return out >>> class Checker(object): ... def check(self, object, name): ... log.append(('check %s' % name)) ... def check_getattr(self, object, name): ... log.append(('check_getattr %s' % name)) ... def proxy(self, object): ... return 1 >>> def f(): ... pass >>> p = ProxyFactory(f, Checker()) >>> p.__name__ 1 >>> dump() 'check_getattr __name__' >>> p() 1 >>> dump() 'check __call__' But, if the checker has a __setitem__ method: >>> def __setitem__(self, object, name): ... log.append(('__setitem__ %s' % name)) >>> Checker.__setitem__ = __setitem__ It will be used rather than either check or check_getattr: >>> p.__name__ 1 >>> dump() '__setitem__ __name__' >>> p() 1 >>> dump() '__setitem__ __call__' If a checker has a __getitem__ method: >>> def __getitem__(self, object): ... return 2 >>> Checker.__getitem__ = __getitem__ It will be used rather than it's proxy method: >>> p.__name__ 2 >>> dump() '__setitem__ __name__' >>> p() 2 >>> dump() '__setitem__ __call__' """ class LocationProxySecurityCheckerTests(unittest.TestCase): def test_LocationProxy_gets_a_security_checker_when_importing_z_security( self): # Regression test for a problem introduced in 3.8.1 and fixed in # 3.8.3. For details see change log. import sys from zope.location.location import LocationProxy import zope.security from zope.security._compat import reload # This attribute is set when zope.security.decorator is imported, to # show that it will be set too, if zope.security.proxy is imported # we set it to a different value at first: del LocationProxy.__Security_checker__ self.assertFalse( hasattr(LocationProxy, '__Security_checker__')) # After deleting zope.security.decorator and reloading # zope.security.proxy the attribute is set again: del sys.modules["zope.security.decorator"] reload(zope.security) self.assertTrue( hasattr(LocationProxy, '__Security_checker__')) def test_suite(): suite = unittest.TestSuite(( unittest.makeSuite(ProxyPyTests), unittest.makeSuite(Test_getTestProxyItems), unittest.makeSuite(Test_isinstance), # pre-geddon unittest.makeSuite(ProxyTests), unittest.makeSuite(LocationProxySecurityCheckerTests), )) if not (PYPY or PURE_PYTHON): suite.addTest(unittest.makeSuite(ProxyCTests)) return suite zope.security-4.0.3/src/zope/security/tests/test_permission.py0000664000175000017500000001741212450532147026075 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2004 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Test permissions """ import unittest class PermissionTests(unittest.TestCase): def _getTargetClass(self): from zope.security.permission import Permission return Permission def _makeOne(self, id, title=None, description=None): klass = self._getTargetClass() if description is None: if title is None: return klass(id) return klass(id, title) if title is None: return klass(id, description=description) return klass(id, title, description) def test_class_conforms_to_IPermission(self): from zope.interface.verify import verifyClass from zope.security.interfaces import IPermission verifyClass(IPermission, self._getTargetClass()) def test_instance_conforms_to_IPermission(self): from zope.interface.verify import verifyObject from zope.security.interfaces import IPermission verifyObject(IPermission, self._makeOne('testing')) def test_ctor_only_id(self): permission = self._makeOne('testing') self.assertEqual(permission.id, 'testing') self.assertEqual(permission.title, '') self.assertEqual(permission.description, '') def test_ctor_w_title_and_description(self): permission = self._makeOne('testing', 'TITLE', 'DESCRIPTION') self.assertEqual(permission.id, 'testing') self.assertEqual(permission.title, 'TITLE') self.assertEqual(permission.description, 'DESCRIPTION') class Test_checkPermission(unittest.TestCase): def setUp(self): from zope.component.testing import setUp setUp() def tearDown(self): from zope.component.testing import tearDown tearDown() def _callFUT(self, context, permission_id): from zope.security.permission import checkPermission return checkPermission(context, permission_id) def test_w_CheckerPublic(self): from zope.security.checker import CheckerPublic self._callFUT(None, CheckerPublic) # no raise def test_miss(self): self.assertRaises(ValueError, self._callFUT, None, 'nonesuch') def test_hit(self): from zope.component import provideUtility from zope.security.interfaces import IPermission permission = object() provideUtility(permission, IPermission, 'testing') self._callFUT(None, 'testing') # no raise class Test_allPermissions(unittest.TestCase): def setUp(self): from zope.component.testing import setUp setUp() def tearDown(self): from zope.component.testing import tearDown tearDown() def _callFUT(self): from zope.security.permission import allPermissions return allPermissions() def test_empty(self): self.assertEqual(list(self._callFUT()), []) def test_w_registration(self): self.assertEqual(list(self._callFUT()), []) from zope.component import provideUtility from zope.security.interfaces import IPermission permission = object() provideUtility(permission, IPermission, 'testing') self.assertEqual(list(self._callFUT()), ['testing']) def test_skips_zope_Public(self): self.assertEqual(list(self._callFUT()), []) from zope.component import provideUtility from zope.security.checker import CheckerPublic from zope.security.interfaces import IPermission permission = object() provideUtility(permission, IPermission, 'testing') provideUtility(CheckerPublic, IPermission, 'zope.Public') self.assertEqual(list(self._callFUT()), ['testing']) class Test_PermissionsVocabulary(unittest.TestCase): def setUp(self): from zope.component.testing import setUp setUp() def tearDown(self): from zope.component.testing import tearDown tearDown() def _callFUT(self): from zope.security.permission import PermissionsVocabulary return PermissionsVocabulary() def test_empty(self): from zope.schema.vocabulary import SimpleVocabulary vocabulary = self._callFUT() self.assertTrue(isinstance(vocabulary, SimpleVocabulary)) self.assertEqual(list(vocabulary), []) def test_w_registration(self): self.assertEqual(list(self._callFUT()), []) from zope.component import provideUtility from zope.security.interfaces import IPermission permission = object() provideUtility(permission, IPermission, 'testing') vocabulary = self._callFUT() self.assertEqual([x.token for x in vocabulary], ['testing']) def test_includes_zope_Public(self): self.assertEqual(list(self._callFUT()), []) from zope.component import provideUtility from zope.security.checker import CheckerPublic from zope.security.interfaces import IPermission permission = object() provideUtility(permission, IPermission, 'testing') provideUtility(CheckerPublic, IPermission, 'zope.Public') vocabulary = self._callFUT() self.assertEqual(sorted([x.token for x in vocabulary]), ['testing', 'zope.Public']) class Test_PermissionIdsVocabulary(unittest.TestCase): def setUp(self): from zope.component.testing import setUp setUp() def tearDown(self): from zope.component.testing import tearDown tearDown() def _callFUT(self): from zope.security.permission import PermissionIdsVocabulary return PermissionIdsVocabulary() def test_empty(self): from zope.schema.vocabulary import SimpleVocabulary vocabulary = self._callFUT() self.assertTrue(isinstance(vocabulary, SimpleVocabulary)) self.assertEqual(list(vocabulary), []) def test_w_registration(self): self.assertEqual(list(self._callFUT()), []) from zope.component import provideUtility from zope.security.interfaces import IPermission permission = object() provideUtility(permission, IPermission, 'testing') vocabulary = self._callFUT() self.assertEqual([x.value for x in vocabulary], ['testing']) self.assertEqual([x.token for x in vocabulary], ['testing']) def test_includes_zope_Public(self): self.assertEqual(list(self._callFUT()), []) from zope.component import provideUtility from zope.security.checker import CheckerPublic from zope.security.interfaces import IPermission permission = object() provideUtility(permission, IPermission, 'testing') provideUtility(CheckerPublic, IPermission, 'zope.Public') vocabulary = self._callFUT() self.assertEqual([x.value for x in vocabulary], [CheckerPublic, 'testing']) self.assertEqual([x.token for x in vocabulary], ['zope.Public', 'testing']) def test_suite(): return unittest.TestSuite([ unittest.makeSuite(PermissionTests), unittest.makeSuite(Test_checkPermission), unittest.makeSuite(Test_allPermissions), unittest.makeSuite(Test_PermissionsVocabulary), unittest.makeSuite(Test_PermissionIdsVocabulary), ]) zope.security-4.0.3/src/zope/security/tests/exampleclass.py0000664000175000017500000000153412450532147025325 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2003 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Example test classes """ from zope.interface import Interface class ExampleClass(object): pass class IExample(Interface): pass class IExample2(Interface): pass class IExampleContainer(Interface): pass zope.security-4.0.3/src/zope/security/tests/adapter.py0000664000175000017500000000264112450532147024264 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2004 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Sample adapter class for testing """ from zope.interface import Interface from zope.interface import implementer from zope.component import adapter from .components import IContent class I1(Interface): pass class I2(Interface): pass class I3(Interface): def f1(): pass def f2(): pass def f3(): pass class IS(Interface): pass class Adapter(object): def __init__(self, *args): self.context = args @implementer(I1) class A1(Adapter): pass @implementer(I2) class A2(Adapter): pass @adapter(IContent, I1, I2) @implementer(I3) class A3(Adapter): pass class A4: pass a4 = A4() @implementer(I1, I2) class A5: pass a5 = A5() def Handler(content, *args): # uninteresting handler content.args = getattr(content, 'args', ()) + (args, ) zope.security-4.0.3/src/zope/security/tests/test_location.py0000664000175000017500000000360112450532147025510 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2003 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Test location support """ import unittest def _skip_wo_zope_location(testfunc): try: import zope.location except ImportError: from functools import update_wrapper def dummy(self): pass update_wrapper(dummy, testfunc) return dummy else: return testfunc class LocationSecurityProxyTests(unittest.TestCase): @_skip_wo_zope_location def test_locationproxy_security(self): from zope.location.location import LocationProxy from zope.security.checker import defineChecker from zope.security.checker import NamesChecker from zope.security.proxy import ProxyFactory class Unlocated(object): a = 'a' unlocated = Unlocated() located = LocationProxy(unlocated) # define a checker for the unlocated object, which will also be # used by the security proxy as the LocationProxy defines # __Security_checker__: unlocatedChecker = NamesChecker(['a']) defineChecker(Unlocated, unlocatedChecker) secure_located = ProxyFactory(located) self.assertEqual(secure_located.a, 'a') def test_suite(): return unittest.TestSuite(( unittest.makeSuite(LocationSecurityProxyTests), )) zope.security-4.0.3/src/zope/security/tests/redefineperms.zcml0000664000175000017500000000130312450532147026003 0ustar tseavertseaver00000000000000 zope.security-4.0.3/src/zope/security/tests/test_simplepolicies.py0000664000175000017500000001121512450532147026721 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2013 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## import unittest class ConformsToIInteraction(object): def test_class_conforms_to_IInteraction(self): from zope.interface.verify import verifyClass from zope.security.interfaces import IInteraction verifyClass(IInteraction, self._getTargetClass()) def test_instance_conforms_to_IInteraction(self): from zope.interface.verify import verifyObject from zope.security.interfaces import IInteraction verifyObject(IInteraction, self._makeOne()) class ParanoidSecurityPolicyTests(unittest.TestCase, ConformsToIInteraction, ): def _getTargetClass(self): from zope.security.simplepolicies import ParanoidSecurityPolicy return ParanoidSecurityPolicy def _makeOne(self, *participations): return self._getTargetClass()(*participations) def test_ctor_no_participations(self): policy = self._makeOne() self.assertEqual(policy.participations, []) def test_ctor_w_participations(self): class Participation(object): interaction = None p1, p2, p3 = Participation(), Participation(), Participation() policy = self._makeOne(p1, p2, p3) self.assertEqual(policy.participations, [p1, p2, p3]) self.assertTrue(p1.interaction is policy) self.assertTrue(p2.interaction is policy) self.assertTrue(p3.interaction is policy) def test_add_w_foreign_participation(self): class Participation(object): interaction = object() policy = self._makeOne() self.assertRaises(ValueError, policy.add, Participation()) def test_remove_w_foreign_participation(self): class Participation(object): interaction = object() policy = self._makeOne() self.assertRaises(ValueError, policy.remove, Participation()) def test_remove(self): class Participation(object): interaction = None p1, p2, p3 = Participation(), Participation(), Participation() policy = self._makeOne(p1, p2, p3) policy.remove(p2) target = object() self.assertEqual(policy.participations, [p1, p3]) self.assertTrue(p1.interaction is policy) self.assertTrue(p2.interaction is None) self.assertTrue(p3.interaction is policy) def test_checkPermission_w_public(self): from zope.security.checker import CheckerPublic policy = self._makeOne() target = object() self.assertTrue(policy.checkPermission(CheckerPublic, target)) def test_checkPermission_w_non_public_only_system_user(self): from zope.security._definitions import system_user class Participation(object): interaction = None principal = system_user policy = self._makeOne(Participation()) permission = object() target = object() self.assertTrue(policy.checkPermission(permission, target)) def test_checkPermission_w_non_public_other_user(self): class Participation(object): interaction = None principal = object() policy = self._makeOne(Participation()) permission = object() target = object() self.assertFalse(policy.checkPermission(permission, target)) class PermissiveSecurityPolicyTests(unittest.TestCase, ConformsToIInteraction, ): def _getTargetClass(self): from zope.security.simplepolicies import PermissiveSecurityPolicy return PermissiveSecurityPolicy def _makeOne(self, *participations): return self._getTargetClass()(*participations) def test_checkPermission_w_public(self): policy = self._makeOne() permission = object() target = object() self.assertTrue(policy.checkPermission(permission, target)) def test_suite(): return unittest.TestSuite(( unittest.makeSuite(ParanoidSecurityPolicyTests), unittest.makeSuite(PermissiveSecurityPolicyTests), )) zope.security-4.0.3/src/zope/security/tests/modulehookup.py0000664000175000017500000000215712450532147025361 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Preliminaries to hookup a test suite with the external TestModule. This is necessary because the test framework interferes with seeing changes in the running modules via the module namespace. This enables having some subject classes, instances, permissions, etc, that don't live in the test modules, themselves. """ from zope.interface import Interface from zope.security.tests import emptymodule as TestModule class I(Interface): def m1(): pass def m2(): pass zope.security-4.0.3/src/zope/security/tests/test_adapter.py0000664000175000017500000005201312450532147025321 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2004 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## import unittest def _skip_wo_zope_location(testfunc): try: import zope.location except ImportError: from functools import update_wrapper def dummy(self): pass update_wrapper(dummy, testfunc) return dummy else: return testfunc class Test_assertLocation(unittest.TestCase): def _callFUT(self, adapter, parent): from zope.security.adapter import assertLocation return assertLocation(adapter, parent) @_skip_wo_zope_location def test_w_non_ILocation(self): from zope.location import LocationProxy from zope.proxy import getProxiedObject class _NotAdapter(object): pass adapter = _NotAdapter() parent = object() returned = self._callFUT(adapter, parent) self.assertTrue(isinstance(returned, LocationProxy)) self.assertTrue(getProxiedObject(returned) is adapter) self.assertTrue(returned.__parent__ is parent) @_skip_wo_zope_location def test_w_ILocation_no_parent(self): from zope.interface import implementer from zope.location import ILocation @implementer(ILocation) class _Adapter(object): __parent__ = None adapter = _Adapter() parent = object() returned = self._callFUT(adapter, parent) self.assertTrue(returned is adapter) self.assertTrue(returned.__parent__ is parent) @_skip_wo_zope_location def test_w_ILocation_w_parent(self): from zope.interface import implementer from zope.location import ILocation parent = object() @implementer(ILocation) class _Adapter(object): __parent__ = parent adapter = _Adapter() new_parent = object() returned = self._callFUT(adapter, new_parent) self.assertTrue(returned is adapter) self.assertTrue(returned.__parent__ is parent) class LocatingTrustedAdapterFactoryTests(unittest.TestCase): def _getTargetClass(self): from zope.security.adapter import LocatingTrustedAdapterFactory return LocatingTrustedAdapterFactory def _makeOne(self, factory): return self._getTargetClass()(factory) def _makeFactory(self): class _Factory(object): __name__ = 'testing' __module__ = 'zope.security.tests.test_adapter' def __call__(self, *args): self._called_with = args return self return _Factory() def test_ctor(self): factory = self._makeFactory() ltaf = self._makeOne(factory) self.assertTrue(ltaf.factory is factory) self.assertEqual(ltaf.__name__, 'testing') self.assertEqual(ltaf.__module__, 'zope.security.tests.test_adapter') @_skip_wo_zope_location def test__call__w_non_ILocation_non_spacesuit(self): factory = self._makeFactory() ltaf = self._makeOne(factory) class _NotAdapter(object): pass adapter = _NotAdapter() before = factory.__dict__.copy() returned = ltaf(adapter) self.assertTrue(returned is factory) after = dict([(k, v) for k, v in returned.__dict__.items() if k != '_called_with']) self.assertEqual(factory._called_with, (adapter,)) self.assertEqual(after, before) # no added attrs @_skip_wo_zope_location def test__call__w_non_ILocation_non_spacesuit_multiple_args(self): factory = self._makeFactory() ltaf = self._makeOne(factory) class _NotAdapter(object): pass adapter = _NotAdapter() extra = object() before = factory.__dict__.copy() returned = ltaf(adapter, extra) self.assertTrue(returned is factory) after = dict([(k, v) for k, v in returned.__dict__.items() if k != '_called_with']) self.assertEqual(factory._called_with, (adapter, extra)) self.assertEqual(after, before) # no added attrs @_skip_wo_zope_location def test__call__w_ILocation_w_existing_parent_non_spacesuit(self): from zope.interface import directlyProvides from zope.location import ILocation factory = self._makeFactory() parent = factory.__parent__ = object() directlyProvides(factory, ILocation) ltaf = self._makeOne(factory) class _NotAdapter(object): pass adapter = _NotAdapter() before = factory.__dict__.copy() returned = ltaf(adapter) self.assertTrue(returned is factory) self.assertTrue(returned.__parent__ is parent) @_skip_wo_zope_location def test__call__w_ILocation_wo_existing_parent_non_spacesuit(self): from zope.interface import directlyProvides from zope.location import ILocation factory = self._makeFactory() factory.__parent__ = None directlyProvides(factory, ILocation) ltaf = self._makeOne(factory) class _NotAdapter(object): pass adapter = _NotAdapter() before = factory.__dict__.copy() returned = ltaf(adapter) self.assertTrue(returned is factory) self.assertTrue(returned.__parent__ is adapter) @_skip_wo_zope_location def test__call__w_non_ILocation_w_spacesuit(self): from zope.proxy import getProxiedObject from zope.security.proxy import getObject from zope.security.proxy import ProxyFactory from zope.security.proxy import removeSecurityProxy factory = self._makeFactory() ltaf = self._makeOne(factory) class _NotAdapter(object): pass adapter = _NotAdapter() proxy = ProxyFactory(adapter) before = factory.__dict__.copy() returned = ltaf(proxy) self.assertFalse(returned is factory) ploc = removeSecurityProxy(returned) self.assertTrue(ploc.__parent__ is adapter) unwrapped = getProxiedObject(ploc) self.assertTrue(unwrapped is factory) after = dict([(k, v) for k, v in unwrapped.__dict__.items() if k not in ('_called_with',)]) self.assertEqual(factory._called_with, (adapter,)) self.assertEqual(after, before) # no added attrs @_skip_wo_zope_location def test__call__w_non_ILocation_w_spacesuit_multiple_args(self): from zope.proxy import getProxiedObject from zope.security.proxy import ProxyFactory from zope.security.proxy import removeSecurityProxy factory = self._makeFactory() ltaf = self._makeOne(factory) class _NotAdapter(object): pass adapter = _NotAdapter() extra = object() proxy = ProxyFactory(adapter) before = factory.__dict__.copy() returned = ltaf(proxy, extra) self.assertFalse(returned is factory) ploc = removeSecurityProxy(returned) self.assertTrue(ploc.__parent__ is adapter) unwrapped = getProxiedObject(ploc) self.assertTrue(unwrapped is factory) after = dict([(k, v) for k, v in unwrapped.__dict__.items() if k not in ('_called_with',)]) self.assertEqual(factory._called_with, (adapter, extra)) self.assertEqual(after, before) # no added attrs @_skip_wo_zope_location def test__call__w_non_ILocation_multiple_args_extra_spacesuit(self): from zope.proxy import getProxiedObject from zope.security.proxy import ProxyFactory from zope.security.proxy import removeSecurityProxy factory = self._makeFactory() ltaf = self._makeOne(factory) class _NotAdapter(object): pass class _Extra(object): pass adapter = _NotAdapter() extra = _Extra() proxy = ProxyFactory(extra) before = factory.__dict__.copy() returned = ltaf(adapter, proxy) self.assertFalse(returned is factory) ploc = removeSecurityProxy(returned) self.assertTrue(ploc.__parent__ is adapter) unwrapped = getProxiedObject(ploc) self.assertTrue(unwrapped is factory) after = dict([(k, v) for k, v in unwrapped.__dict__.items() if k not in ('_called_with',)]) self.assertEqual(factory._called_with, (adapter, extra)) self.assertEqual(after, before) # no added attrs @_skip_wo_zope_location def test__call__w_ILocation_w_spacesuit(self): from zope.interface import directlyProvides from zope.location import ILocation from zope.security.proxy import getObject from zope.security.proxy import ProxyFactory from zope.security.proxy import removeSecurityProxy factory = self._makeFactory() factory.__parent__ = factory.__name__ = None directlyProvides(factory, ILocation) ltaf = self._makeOne(factory) class _Adapter(object): pass adapter = _Adapter() proxy = ProxyFactory(adapter) before = dict([(k, v) for k, v in factory.__dict__.items() if k not in ('_called_with', '__parent__')]) returned = ltaf(proxy) self.assertFalse(returned is factory) ploc = removeSecurityProxy(returned) self.assertTrue(ploc.__parent__ is adapter) unwrapped = getObject(ploc) self.assertTrue(unwrapped is factory) after = dict([(k, v) for k, v in unwrapped.__dict__.items() if k not in ('_called_with', '__parent__')]) self.assertEqual(factory._called_with, (adapter,)) self.assertTrue(factory.__parent__ is adapter) self.assertEqual(after, before) # no added attrs @_skip_wo_zope_location def test__call__w_ILocation_w_spacesuit_w_existing_parent(self): from zope.interface import directlyProvides from zope.location import ILocation from zope.security.proxy import getObject from zope.security.proxy import ProxyFactory from zope.security.proxy import removeSecurityProxy factory = self._makeFactory() factory.__name__ = None factory.__parent__ = parent = object() directlyProvides(factory, ILocation) ltaf = self._makeOne(factory) class _Adapter(object): pass adapter = _Adapter() proxy = ProxyFactory(adapter) before = dict([(k, v) for k, v in factory.__dict__.items() if k not in ('_called_with', '__parent__')]) returned = ltaf(proxy) self.assertFalse(returned is factory) ploc = removeSecurityProxy(returned) self.assertTrue(ploc.__parent__ is parent) unwrapped = getObject(ploc) self.assertTrue(unwrapped is factory) after = dict([(k, v) for k, v in unwrapped.__dict__.items() if k not in ('_called_with', '__parent__')]) self.assertEqual(factory._called_with, (adapter,)) self.assertEqual(after, before) # no added attrs class TrustedAdapterFactoryTests(unittest.TestCase): def _getTargetClass(self): from zope.security.adapter import TrustedAdapterFactory return TrustedAdapterFactory def _makeOne(self, factory): return self._getTargetClass()(factory) def _makeFactory(self): class _Factory(object): __name__ = 'testing' __module__ = 'zope.security.tests.test_adapter' def __call__(self, *args): self._called_with = args return self return _Factory() @_skip_wo_zope_location def test__call__w_non_ILocation_w_spacesuit(self): from zope.security.proxy import ProxyFactory from zope.security.proxy import removeSecurityProxy factory = self._makeFactory() ltaf = self._makeOne(factory) class _NotAdapter(object): pass adapter = _NotAdapter() proxy = ProxyFactory(adapter) before = factory.__dict__.copy() returned = ltaf(proxy) self.assertFalse(returned is factory) unwrapped = removeSecurityProxy(returned) self.assertTrue('__parent__' not in unwrapped.__dict__) self.assertTrue(unwrapped is factory) after = dict([(k, v) for k, v in unwrapped.__dict__.items() if k not in ('_called_with',)]) self.assertEqual(factory._called_with, (adapter,)) self.assertEqual(after, before) # no added attrs @_skip_wo_zope_location def test__call__w_non_ILocation_w_spacesuit_multiple_args(self): from zope.security.proxy import ProxyFactory from zope.security.proxy import removeSecurityProxy factory = self._makeFactory() ltaf = self._makeOne(factory) class _NotAdapter(object): pass adapter = _NotAdapter() extra = object() proxy = ProxyFactory(adapter) before = factory.__dict__.copy() returned = ltaf(proxy, extra) self.assertFalse(returned is factory) unwrapped = removeSecurityProxy(returned) self.assertTrue('__parent__' not in unwrapped.__dict__) self.assertTrue(unwrapped is factory) after = dict([(k, v) for k, v in unwrapped.__dict__.items() if k not in ('_called_with',)]) self.assertEqual(factory._called_with, (adapter, extra)) self.assertEqual(after, before) # no added attrs @_skip_wo_zope_location def test__call__w_non_ILocation_multiple_args_extra_spacesuit(self): from zope.security.proxy import ProxyFactory from zope.security.proxy import removeSecurityProxy factory = self._makeFactory() ltaf = self._makeOne(factory) class _NotAdapter(object): pass class _Extra(object): pass adapter = _NotAdapter() extra = _Extra() proxy = ProxyFactory(extra) before = factory.__dict__.copy() returned = ltaf(adapter, proxy) self.assertFalse(returned is factory) unwrapped = removeSecurityProxy(returned) self.assertTrue('__parent__' not in unwrapped.__dict__) self.assertTrue(unwrapped is factory) after = dict([(k, v) for k, v in unwrapped.__dict__.items() if k not in ('_called_with',)]) self.assertEqual(factory._called_with, (adapter, extra)) self.assertEqual(after, before) # no added attrs @_skip_wo_zope_location def test__call__w_ILocation_w_spacesuit(self): from zope.interface import directlyProvides from zope.location import ILocation from zope.security.proxy import ProxyFactory from zope.security.proxy import removeSecurityProxy factory = self._makeFactory() factory.__parent__ = factory.__name__ = None directlyProvides(factory, ILocation) ltaf = self._makeOne(factory) class _Adapter(object): pass adapter = _Adapter() proxy = ProxyFactory(adapter) before = dict([(k, v) for k, v in factory.__dict__.items() if k not in ('_called_with', '__parent__')]) returned = ltaf(proxy) self.assertFalse(returned is factory) unwrapped = removeSecurityProxy(returned) self.assertTrue(unwrapped.__parent__ is adapter) self.assertTrue(unwrapped is factory) after = dict([(k, v) for k, v in unwrapped.__dict__.items() if k not in ('_called_with', '__parent__')]) self.assertEqual(factory._called_with, (adapter,)) self.assertEqual(after, before) # no added attrs @_skip_wo_zope_location def test__call__w_ILocation_w_spacesuit_w_existing_parent(self): from zope.interface import directlyProvides from zope.location import ILocation from zope.security.proxy import ProxyFactory from zope.security.proxy import removeSecurityProxy factory = self._makeFactory() factory.__name__ = None factory.__parent__ = parent = object() directlyProvides(factory, ILocation) ltaf = self._makeOne(factory) class _Adapter(object): pass adapter = _Adapter() proxy = ProxyFactory(adapter) before = dict([(k, v) for k, v in factory.__dict__.items() if k not in ('_called_with', '__parent__')]) returned = ltaf(proxy) self.assertFalse(returned is factory) unwrapped = removeSecurityProxy(returned) self.assertTrue(unwrapped.__parent__ is parent) self.assertTrue(unwrapped is factory) after = dict([(k, v) for k, v in unwrapped.__dict__.items() if k not in ('_called_with', '__parent__')]) self.assertEqual(factory._called_with, (adapter,)) self.assertEqual(after, before) # no added attrs class LocatingUntrustedAdapterFactoryTests(unittest.TestCase): def _getTargetClass(self): from zope.security.adapter import LocatingUntrustedAdapterFactory return LocatingUntrustedAdapterFactory def _makeOne(self, factory): return self._getTargetClass()(factory) def _makeFactory(self): class _Factory(object): __name__ = 'testing' __module__ = 'zope.security.tests.test_adapter' def __call__(self, *args): self._called_with = args return self return _Factory() def test_ctor(self): factory = self._makeFactory() ltaf = self._makeOne(factory) self.assertTrue(ltaf.factory is factory) self.assertEqual(ltaf.__name__, 'testing') self.assertEqual(ltaf.__module__, 'zope.security.tests.test_adapter') @_skip_wo_zope_location def test__call__w_non_ILocation(self): from zope.proxy import getProxiedObject factory = self._makeFactory() ltaf = self._makeOne(factory) class _NotAdapter(object): pass adapter = _NotAdapter() before = factory.__dict__.copy() returned = ltaf(adapter) self.assertFalse(returned is factory) unwrapped = getProxiedObject(returned) self.assertTrue(unwrapped is factory) after = dict([(k, v) for k, v in returned.__dict__.items() if k != '_called_with']) self.assertEqual(factory._called_with, (adapter,)) self.assertEqual(after, before) # no added attrs @_skip_wo_zope_location def test__call__w_non_ILocation_multiple_args(self): from zope.proxy import getProxiedObject factory = self._makeFactory() ltaf = self._makeOne(factory) class _NotAdapter(object): pass adapter = _NotAdapter() extra = object() before = factory.__dict__.copy() returned = ltaf(adapter, extra) self.assertFalse(returned is factory) unwrapped = getProxiedObject(returned) self.assertTrue(unwrapped is factory) after = dict([(k, v) for k, v in returned.__dict__.items() if k != '_called_with']) self.assertEqual(factory._called_with, (adapter, extra)) self.assertEqual(after, before) # no added attrs @_skip_wo_zope_location def test__call__w_ILocation_w_existing_parent(self): from zope.interface import directlyProvides from zope.location import ILocation factory = self._makeFactory() parent = factory.__parent__ = object() directlyProvides(factory, ILocation) ltaf = self._makeOne(factory) class _NotAdapter(object): pass adapter = _NotAdapter() before = factory.__dict__.copy() returned = ltaf(adapter) self.assertTrue(returned is factory) self.assertTrue(returned.__parent__ is parent) @_skip_wo_zope_location def test__call__w_ILocation_wo_existing_parent(self): from zope.interface import directlyProvides from zope.location import ILocation factory = self._makeFactory() factory.__parent__ = None directlyProvides(factory, ILocation) ltaf = self._makeOne(factory) class _NotAdapter(object): pass adapter = _NotAdapter() before = factory.__dict__.copy() returned = ltaf(adapter) self.assertTrue(returned is factory) self.assertTrue(returned.__parent__ is adapter) def test_suite(): return unittest.TestSuite(( unittest.makeSuite(Test_assertLocation), unittest.makeSuite(LocatingTrustedAdapterFactoryTests), unittest.makeSuite(TrustedAdapterFactoryTests), unittest.makeSuite(LocatingUntrustedAdapterFactoryTests), )) zope.security-4.0.3/src/zope/security/tests/test_checker.py0000664000175000017500000023370712533415227025321 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Tests for zope.security.checker """ import unittest def _skip_if_not_Py2(testfunc): import sys from functools import update_wrapper if sys.version_info[0] >= 3: def dummy(self): pass update_wrapper(dummy, testfunc) return dummy return testfunc class Test_ProxyFactory(unittest.TestCase): def _callFUT(self, object, checker=None): from zope.security.checker import ProxyFactory return ProxyFactory(object, checker) def test_w_already_proxied_no_checker(self): from zope.security.proxy import Proxy, getChecker obj = object() def _check(*x): pass proxy = Proxy(obj, _check) returned = self._callFUT(proxy, None) self.assertTrue(returned is proxy) self.assertTrue(getChecker(returned) is _check) def test_w_already_proxied_same_checker(self): from zope.security.proxy import Proxy, getChecker obj = object() def _check(*x): pass proxy = Proxy(obj, _check) returned = self._callFUT(proxy, _check) self.assertTrue(returned is proxy) self.assertTrue(getChecker(returned) is _check) def test_w_already_proxied_different_checker(self): from zope.security.proxy import Proxy obj = object() def _check(*x): pass proxy = Proxy(obj, _check) def _sneaky(*x): pass self.assertRaises(TypeError, self._callFUT, proxy, _sneaky) def test_w_explicit_checker(self): from zope.security.proxy import getChecker obj = object() def _check(*x): pass returned = self._callFUT(obj, _check) self.assertFalse(returned is obj) self.assertTrue(getChecker(returned) is _check) def test_no_checker_no_dunder_no_select(self): obj = object() returned = self._callFUT(obj) self.assertTrue(returned is obj) def test_no_checker_w_dunder(self): from zope.security.proxy import getChecker, getObject _check = object() # don't use a func, due to bound method class _WithChecker(object): __Security_checker__ = _check obj = _WithChecker() returned = self._callFUT(obj) self.assertFalse(returned is obj) self.assertTrue(getObject(returned) is obj) self.assertTrue(getChecker(returned) is _check) def test_no_checker_no_dunder_w_select(self): from zope.security.checker import Checker from zope.security.checker import _checkers from zope.security.checker import _clear from zope.security.proxy import getChecker, getObject class _Obj(object): pass obj = _Obj() _checker = Checker({}) def _check(*args): return _checker _checkers[_Obj] = _check try: returned = self._callFUT(obj) self.assertFalse(returned is obj) self.assertTrue(getObject(returned) is obj) self.assertTrue(getChecker(returned) is _checker) finally: _clear() class Test_canWrite(unittest.TestCase): def _callFUT(self, obj, name): from zope.security.checker import canWrite return canWrite(obj, name) def _makeChecker(self, ch_get=None, ch_set=None): class _Checker(object): def check_getattr(self, obj, name): if ch_get is not None: raise ch_get() def check_setattr(self, obj, name): if ch_set is not None: raise ch_set() return _Checker() def test_ok(self): from zope.security.proxy import Proxy obj = object() proxy = Proxy(obj, self._makeChecker()) self.assertTrue(self._callFUT(proxy, 'whatever')) def test_w_setattr_unauth(self): from zope.security.interfaces import Unauthorized from zope.security.proxy import Proxy obj = object() proxy = Proxy(obj, self._makeChecker(ch_set=Unauthorized)) self.assertFalse(self._callFUT(proxy, 'whatever')) def test_w_setattr_forbidden_getattr_allowed(self): from zope.security.interfaces import ForbiddenAttribute from zope.security.proxy import Proxy obj = object() proxy = Proxy(obj, self._makeChecker(ch_set=ForbiddenAttribute)) self.assertFalse(self._callFUT(proxy, 'whatever')) def test_w_setattr_forbidden_getattr_unauth(self): from zope.security.interfaces import ForbiddenAttribute from zope.security.interfaces import Unauthorized from zope.security.proxy import Proxy obj = object() proxy = Proxy(obj, self._makeChecker(ch_get=Unauthorized, ch_set=ForbiddenAttribute)) self.assertFalse(self._callFUT(proxy, 'whatever')) def test_w_setattr_forbidden_getattr_forbidden(self): from zope.security.interfaces import ForbiddenAttribute from zope.security.proxy import Proxy obj = object() proxy = Proxy(obj, self._makeChecker(ch_get=ForbiddenAttribute, ch_set=ForbiddenAttribute)) self.assertRaises(ForbiddenAttribute, self._callFUT, proxy, 'whatever') class Test_canAccess(unittest.TestCase): def _callFUT(self, obj, name): from zope.security.checker import canAccess return canAccess(obj, name) def _makeChecker(self, ch_get=None): class _Checker(object): def check_getattr(self, obj, name): if ch_get is not None: raise ch_get() return _Checker() def test_ok(self): from zope.security.proxy import Proxy obj = object() proxy = Proxy(obj, self._makeChecker()) self.assertTrue(self._callFUT(proxy, 'whatever')) def test_w_getattr_unauth(self): from zope.security.interfaces import Unauthorized from zope.security.proxy import Proxy obj = object() proxy = Proxy(obj, self._makeChecker(ch_get=Unauthorized)) self.assertFalse(self._callFUT(proxy, 'whatever')) def test_w_setattr_forbidden_getattr_allowed(self): from zope.security.interfaces import ForbiddenAttribute from zope.security.proxy import Proxy obj = object() proxy = Proxy(obj, self._makeChecker(ch_get=ForbiddenAttribute)) self.assertRaises(ForbiddenAttribute, self._callFUT, proxy, 'whatever') _marker = [] class CheckerTestsBase(object): def _getTargetClass(self): from zope.security.checker import Checker return Checker def _makeOne(self, get_permissions=_marker, set_permissions=_marker): if get_permissions is _marker: get_permissions = {} if set_permissions is _marker: return self._getTargetClass()(get_permissions) return self._getTargetClass()(get_permissions, set_permissions) def test_class_conforms_to_IChecker(self): from zope.interface.verify import verifyClass from zope.security.interfaces import IChecker verifyClass(IChecker, self._getTargetClass()) def test_instance_conforms_to_IChecker(self): from zope.interface.verify import verifyObject from zope.security.interfaces import IChecker verifyObject(IChecker, self._makeOne()) def test_ctor_w_non_dict_get_permissions(self): self.assertRaises(TypeError, self._makeOne, object()) def test_ctor_w_non_dict_set_permissions(self): self.assertRaises(TypeError, self._makeOne, {}, object()) def test_permission_id_miss(self): checker = self._makeOne() self.assertTrue(checker.permission_id('nonesuch') is None) def test_permission_id_hit(self): checker = self._makeOne({'name': 'PERMISSION'}) self.assertEqual(checker.permission_id('name'), 'PERMISSION') def test_setattr_permission_id_miss_none_set(self): checker = self._makeOne() self.assertTrue(checker.setattr_permission_id('nonesuch') is None) def test_setattr_permission_id_miss(self): checker = self._makeOne(set_permissions={'name': 'PERMISSION'}) self.assertTrue(checker.setattr_permission_id('nonesuch') is None) def test_setattr_permission_id_hit(self): checker = self._makeOne(set_permissions={'name': 'PERMISSION'}) self.assertEqual(checker.setattr_permission_id('name'), 'PERMISSION') def test_check_setattr_miss_none_set(self): from zope.security.interfaces import ForbiddenAttribute checker = self._makeOne() obj = object() self.assertRaises(ForbiddenAttribute, checker.check_setattr, obj, 'nonesuch') def test_check_setattr_miss(self): from zope.security.interfaces import ForbiddenAttribute checker = self._makeOne(set_permissions={'name': 'PERMISSION'}) obj = object() self.assertRaises(ForbiddenAttribute, checker.check_setattr, obj, 'nonesuch') def test_check_setattr_public(self): from zope.security.checker import CheckerPublic checker = self._makeOne(set_permissions={'name': CheckerPublic}) obj = object() self.assertEqual(checker.check_setattr(obj, 'name'), None) def test_check_setattr_w_interaction_allows(self): from zope.security._definitions import thread_local class _Interaction(object): def checkPermission(self, obj, perm): return True checker = self._makeOne(set_permissions={'name': 'view'}) obj = object() thread_local.interaction = _Interaction() try: self.assertEqual(checker.check_setattr(obj, 'name'), None) finally: del thread_local.interaction def test_check_setattr_w_interaction_denies(self): from zope.security.interfaces import Unauthorized from zope.security._definitions import thread_local class _Interaction(object): def checkPermission(self, obj, perm): return False checker = self._makeOne(set_permissions={'name': 'view'}) obj = object() thread_local.interaction = _Interaction() try: self.assertRaises(Unauthorized, checker.check_setattr, obj, 'name') finally: del thread_local.interaction def test_check_miss(self): from zope.security.interfaces import ForbiddenAttribute checker = self._makeOne() obj = object() self.assertRaises(ForbiddenAttribute, checker.check, obj, 'nonesuch') def test_check_available_by_default(self): checker = self._makeOne() obj = object() self.assertEqual(checker.check(obj, '__repr__'), None) def test_check_public(self): from zope.security.checker import CheckerPublic checker = self._makeOne({'name': CheckerPublic}) obj = object() self.assertEqual(checker.check(obj, 'name'), None) def test_check_non_public_w_interaction_allows(self): from zope.security._definitions import thread_local class _Interaction(object): def checkPermission(self, obj, perm): return True checker = self._makeOne({'name': 'view'}) obj = object() thread_local.interaction = _Interaction() try: self.assertEqual(checker.check(obj, 'name'), None) finally: del thread_local.interaction def test_check_non_public_w_interaction_denies(self): from zope.security.interfaces import Unauthorized from zope.security._definitions import thread_local class _Interaction(object): def checkPermission(self, obj, perm): return False checker = self._makeOne({'name': 'view'}) obj = object() thread_local.interaction = _Interaction() try: self.assertRaises(Unauthorized, checker.check, obj, 'name') finally: del thread_local.interaction def test_proxy_already_proxied(self): from zope.security.proxy import Proxy, getChecker obj = object() def _check(*x): pass proxy = Proxy(obj, _check) checker = self._makeOne({'name': 'view'}) returned = checker.proxy(proxy) self.assertTrue(returned is proxy) self.assertTrue(getChecker(returned) is _check) def test_proxy_no_dunder_no_select(self): obj = object() checker = self._makeOne() returned = checker.proxy(obj) self.assertTrue(returned is obj) def test_proxy_no_checker_w_dunder(self): from zope.security.proxy import getChecker, getObject _check = object() # don't use a func, due to bound method class _WithChecker(object): __Security_checker__ = _check obj = _WithChecker() checker = self._makeOne() returned = checker.proxy(obj) self.assertFalse(returned is obj) self.assertTrue(getObject(returned) is obj) self.assertTrue(getChecker(returned) is _check) def test_proxy_no_checker_no_dunder_w_select(self): from zope.security.checker import Checker from zope.security.checker import _checkers from zope.security.checker import _clear from zope.security.proxy import getChecker, getObject class _Obj(object): pass obj = _Obj() _checker = Checker({}) def _check(*args): return _checker _checkers[_Obj] = _check try: checker = self._makeOne() returned = checker.proxy(obj) self.assertFalse(returned is obj) self.assertTrue(getObject(returned) is obj) self.assertTrue(getChecker(returned) is _checker) finally: _clear() class CheckerPyTests(unittest.TestCase, CheckerTestsBase): def _getTargetClass(self): from zope.security.checker import CheckerPy return CheckerPy class CheckerTests(unittest.TestCase, CheckerTestsBase): def _getTargetClass(self): from zope.security.checker import Checker return Checker class TracebackSupplementTests(unittest.TestCase): def _getTargetClass(self): from zope.security.checker import TracebackSupplement return TracebackSupplement def _makeOne(self, obj): return self._getTargetClass()(obj) def test_getInfo_builtin_types(self): from zope.security._compat import _BUILTINS for val, typ in [('', 'str'), (0, 'int'), (1.0, 'float'), ((), 'tuple'), ([], 'list'), ({}, 'dict'), ]: tbs = self._makeOne(val) self.assertEqual(tbs.getInfo().splitlines(), [' - class: %s.%s' % (_BUILTINS, typ), ' - type: %s.%s' % (_BUILTINS, typ), ]) def test_getInfo_newstyle_instance(self): class C(object): pass tbs = self._makeOne(C()) self.assertEqual(tbs.getInfo().splitlines(), [' - class: %s.C' % self.__class__.__module__, ' - type: %s.C' % self.__class__.__module__, ]) @_skip_if_not_Py2 def test_getInfo_classic_instance(self): exec("class C: pass", globals(), locals()) tbs = self._makeOne(locals()['C']()) self.assertEqual(tbs.getInfo().splitlines(), [' - class: %s.C' % self.__class__.__module__, ' - type: __builtin__.instance', ]) class GlobalTests(unittest.TestCase): def _getTargetClass(self): from zope.security.checker import Global return Global def _makeOne(self, name, module=_marker): if module is _marker: return self._getTargetClass()(name) return self._getTargetClass()(name, module) def test_ctor_name_and_module(self): global glob glob = self._makeOne('foo', 'bar.baz') self.assertEqual(glob.__name__, 'foo') self.assertEqual(glob.__module__, 'bar.baz') def test___reduce__(self): glob = self._makeOne('foo', 'bar.baz') self.assertEqual(glob.__reduce__(), 'foo') def test___repr__(self): glob = self._makeOne('foo', 'bar.baz') self.assertEqual(repr(glob), 'Global(foo,bar.baz)') class Test_NamesChecker(unittest.TestCase): def _callFUT(self, *args, **kw): from zope.security.checker import NamesChecker return NamesChecker(*args, **kw) def test_empty_names_no_kw(self): from zope.interface.verify import verifyObject from zope.security.interfaces import IChecker checker = self._callFUT() verifyObject(IChecker, checker) self.assertTrue(checker.permission_id('nonesuch') is None) def test_w_names_no_kw(self): from zope.security.checker import CheckerPublic checker = self._callFUT(('foo', 'bar', 'baz')) self.assertTrue(checker.permission_id('foo') is CheckerPublic) self.assertTrue(checker.permission_id('bar') is CheckerPublic) self.assertTrue(checker.permission_id('baz') is CheckerPublic) self.assertTrue(checker.permission_id('nonesuch') is None) def test_w_names_no_kw_explicit_permission(self): other_perm = object() checker = self._callFUT(('foo', 'bar', 'baz'), permission_id=other_perm) self.assertTrue(checker.permission_id('foo') is other_perm) self.assertTrue(checker.permission_id('bar') is other_perm) self.assertTrue(checker.permission_id('baz') is other_perm) self.assertTrue(checker.permission_id('nonesuch') is None) def test_w_names_w_kw_no_clash(self): from zope.security.checker import CheckerPublic other_perm = object() checker = self._callFUT(('foo', 'bar', 'baz'), bam=other_perm) self.assertTrue(checker.permission_id('foo') is CheckerPublic) self.assertTrue(checker.permission_id('bar') is CheckerPublic) self.assertTrue(checker.permission_id('baz') is CheckerPublic) self.assertTrue(checker.permission_id('bam') is other_perm) self.assertTrue(checker.permission_id('nonesuch') is None) def test_w_names_w_kw_w_clash(self): from zope.security.checker import DuplicationError other_perm = object() self.assertRaises(DuplicationError, self._callFUT, ('foo',), foo=other_perm) class Test_InterfaceChecker(unittest.TestCase): def _callFUT(self, *args, **kw): from zope.security.checker import InterfaceChecker return InterfaceChecker(*args, **kw) def test_simple_iface_wo_kw(self): from zope.interface import Attribute from zope.interface import Interface from zope.security.checker import CheckerPublic class IFoo(Interface): bar = Attribute('Bar') checker = self._callFUT(IFoo) self.assertTrue(checker.permission_id('bar') is CheckerPublic) self.assertTrue(checker.permission_id('nonesuch') is None) def test_simple_iface_w_explicit_permission(self): from zope.interface import Attribute from zope.interface import Interface class IFoo(Interface): bar = Attribute('Bar') other_perm = object() checker = self._callFUT(IFoo, other_perm) self.assertTrue(checker.permission_id('bar') is other_perm) def test_simple_iface_w_kw(self): from zope.interface import Attribute from zope.interface import Interface from zope.security.checker import CheckerPublic class IFoo(Interface): bar = Attribute('Bar') other_perm = object() checker = self._callFUT(IFoo, baz=other_perm) self.assertTrue(checker.permission_id('bar') is CheckerPublic) self.assertTrue(checker.permission_id('baz') is other_perm) self.assertTrue(checker.permission_id('nonesuch') is None) def test_derived_iface(self): from zope.interface import Attribute from zope.interface import Interface from zope.security.checker import CheckerPublic class IFoo(Interface): bar = Attribute('Bar') class IBar(IFoo): baz = Attribute('Baz') checker = self._callFUT(IBar) self.assertTrue(checker.permission_id('bar') is CheckerPublic) self.assertTrue(checker.permission_id('baz') is CheckerPublic) self.assertTrue(checker.permission_id('nonesuch') is None) def test_w_clash(self): from zope.interface import Attribute from zope.interface import Interface from zope.security.checker import DuplicationError class IFoo(Interface): bar = Attribute('Bar') bam = Attribute('Bam') other_perm = object() self.assertRaises(DuplicationError, self._callFUT, IFoo, bar=other_perm) class Test_MultiChecker(unittest.TestCase): def _callFUT(self, specs): from zope.security.checker import MultiChecker return MultiChecker(specs) def test_empty(self): from zope.interface.verify import verifyObject from zope.security.interfaces import IChecker checker = self._callFUT([]) verifyObject(IChecker, checker) self.assertTrue(checker.permission_id('nonesuch') is None) def test_w_spec_as_names(self): from zope.security.checker import CheckerPublic checker = self._callFUT([(('foo', 'bar', 'baz'), CheckerPublic)]) self.assertTrue(checker.permission_id('foo') is CheckerPublic) self.assertTrue(checker.permission_id('bar') is CheckerPublic) self.assertTrue(checker.permission_id('baz') is CheckerPublic) self.assertTrue(checker.permission_id('nonesuch') is None) def test_w_spec_as_iface(self): from zope.interface import Attribute from zope.interface import Interface class IFoo(Interface): bar = Attribute('Bar') other_perm = object() checker = self._callFUT([(IFoo, other_perm)]) self.assertTrue(checker.permission_id('bar') is other_perm) self.assertTrue(checker.permission_id('nonesuch') is None) def test_w_spec_as_names_and_iface(self): from zope.interface import Attribute from zope.interface import Interface from zope.security.checker import CheckerPublic class IFoo(Interface): bar = Attribute('Bar') other_perm = object() checker = self._callFUT([(IFoo, other_perm), (('foo', 'baz'), CheckerPublic)]) self.assertTrue(checker.permission_id('foo') is CheckerPublic) self.assertTrue(checker.permission_id('bar') is other_perm) self.assertTrue(checker.permission_id('baz') is CheckerPublic) self.assertTrue(checker.permission_id('nonesuch') is None) def test_w_spec_as_names_and_iface_clash(self): from zope.interface import Attribute from zope.interface import Interface from zope.security.checker import CheckerPublic from zope.security.checker import DuplicationError class IFoo(Interface): bar = Attribute('Bar') other_perm = object() self.assertRaises(DuplicationError, self._callFUT, [(IFoo, other_perm), (('foo', 'bar'), CheckerPublic)]) def test_w_spec_as_mapping(self): from zope.security.checker import CheckerPublic other_perm = object() spec = {'foo': CheckerPublic, 'bar': other_perm, } checker = self._callFUT([spec]) self.assertTrue(checker.permission_id('foo') is CheckerPublic) self.assertTrue(checker.permission_id('bar') is other_perm) self.assertTrue(checker.permission_id('nonesuch') is None) def test_w_spec_as_names_and_mapping_clash(self): from zope.security.checker import CheckerPublic from zope.security.checker import DuplicationError other_perm = object() spec = {'foo': other_perm, } self.assertRaises(DuplicationError, self._callFUT, [(('foo', 'bar'), CheckerPublic), spec]) class _SelectCheckerBase(object): def setUp(self): from zope.security.checker import _clear _clear() def tearDown(self): from zope.security.checker import _clear _clear() def test_w_basic_types_NoProxy(self): import datetime from zope.i18nmessageid import Message from zope.security._compat import _u msg = Message('msg') for obj in [object(), 42, 3.14, None, _u('text'), b'binary', msg, True, datetime.timedelta(1), datetime.datetime.now(), datetime.date.today(), datetime.datetime.now().time(), datetime.tzinfo(), ]: self.assertTrue(self._callFUT(obj) is None) def test_w_checker_inst(self): from zope.security.checker import Checker from zope.security.checker import _checkers class Foo(object): pass checker = _checkers[Foo] = Checker({}) self.assertTrue(self._callFUT(Foo()) is checker) def test_w_factory_returning_checker(self): from zope.security.checker import Checker from zope.security.checker import _checkers class Foo(object): pass checker = Checker({}) def _factory(obj): return checker _checkers[Foo] = _factory self.assertTrue(self._callFUT(Foo()) is checker) def test_w_factory_returning_NoProxy(self): from zope.security.checker import NoProxy from zope.security.checker import _checkers class Foo(object): pass def _factory(obj): return NoProxy _checkers[Foo] = _factory self.assertTrue(self._callFUT(Foo()) is None) def test_w_factory_returning_None(self): from zope.security.checker import _checkers class Foo(object): pass def _factory(obj): pass _checkers[Foo] = _factory self.assertTrue(self._callFUT(Foo()) is None) def test_w_factory_factory(self): from zope.security.checker import Checker from zope.security.checker import _checkers class Foo(object): pass checker = Checker({}) def _factory(obj): return checker def _factory_factory(obj): return _factory _checkers[Foo] = _factory_factory self.assertTrue(self._callFUT(Foo()) is checker) class Test_selectCheckerPy(unittest.TestCase, _SelectCheckerBase): def _callFUT(self, obj): from zope.security.checker import selectCheckerPy return selectCheckerPy(obj) class Test_selectChecker(unittest.TestCase, _SelectCheckerBase): def _callFUT(self, obj): from zope.security.checker import selectChecker return selectChecker(obj) class Test_getCheckerForInstancesOf(unittest.TestCase): def setUp(self): from zope.security.checker import _clear _clear() def tearDown(self): from zope.security.checker import _clear _clear() def _callFUT(self, obj): from zope.security.checker import getCheckerForInstancesOf return getCheckerForInstancesOf(obj) def test_miss(self): class Unknown(object): pass self.assertTrue(self._callFUT(Unknown) is None) def test_hit(self): from zope.security.checker import _checkers class Foo(object): pass checker = _checkers[Foo] = object() self.assertTrue(self._callFUT(Foo) is checker) class Test_defineChecker(unittest.TestCase): def setUp(self): from zope.security.checker import _clear _clear() def tearDown(self): from zope.security.checker import _clear _clear() def _callFUT(self, type_, checker): from zope.security.checker import defineChecker return defineChecker(type_, checker) def test_w_wrong_type(self): from zope.security._compat import _u checker = object() for obj in [object(), 42, 3.14, None, _u('text'), b'binary', True, ]: self.assertRaises(TypeError, self._callFUT, obj, checker) def test_w_duplicate(self): from zope.exceptions import DuplicationError from zope.security.checker import _checkers class Foo(object): pass checker1, checker2 = object(), object() _checkers[Foo] = checker1 self.assertRaises(DuplicationError, self._callFUT, Foo, checker2) def test_w_newstyle_class(self): from zope.security.checker import _checkers checker = object() class Foo(object): pass self._callFUT(Foo, checker) self.assertTrue(_checkers[Foo] is checker) def test_w_module(self): import zope.interface from zope.security.checker import _checkers checker = object() self._callFUT(zope.interface, checker) self.assertTrue(_checkers[zope.interface] is checker) @_skip_if_not_Py2 def test_w_oldstyle_class(self): from zope.security.checker import _checkers checker = object() class Foo: pass self._callFUT(Foo, checker) self.assertTrue(_checkers[Foo] is checker) class Test_undefineChecker(unittest.TestCase): def setUp(self): from zope.security.checker import _clear _clear() def tearDown(self): from zope.security.checker import _clear _clear() def _callFUT(self, type_): from zope.security.checker import undefineChecker return undefineChecker(type_) def test_miss(self): class Foo(object): pass self.assertRaises(KeyError, self._callFUT, Foo) def test_hit(self): from zope.security.checker import _checkers class Foo(object): pass checker = _checkers[Foo] = object() self._callFUT(Foo) self.assertFalse(Foo in _checkers) class CombinedCheckerTests(unittest.TestCase): def _getTargetClass(self): from zope.security.checker import CombinedChecker return CombinedChecker def _makeOne(self, checker1=None, checker2=None): if checker1 is None: checker1 = self._makeOther() if checker2 is None: checker1 = self._makeOther() return self._getTargetClass()(checker1, checker2) def _makeOther(self, get_permissions=None, set_permissions=None): from zope.security.checker import Checker if get_permissions is None: get_permissions = {} if set_permissions is None: set_permissions = {} return Checker(get_permissions, set_permissions) def test_class_conforms_to_IChecker(self): from zope.interface.verify import verifyClass from zope.security.interfaces import IChecker verifyClass(IChecker, self._getTargetClass()) def test_instance_conforms_to_IChecker(self): from zope.interface.verify import verifyObject from zope.security.interfaces import IChecker verifyObject(IChecker, self._makeOne()) def test_check_lhs_ok_rhs_not_called(self): from zope.security.checker import CheckerPublic from zope.security.checker import Checker class _NeverCalled(Checker): def check(self, *args, **kw): raise AssertionError obj = object() lhs = self._makeOther({'name': CheckerPublic}) rhs = _NeverCalled({}) combined = self._makeOne(lhs, rhs) combined.check(object(), 'name') # no raise def test_check_lhs_unauth_rhs_ok(self): from zope.security.checker import CheckerPublic from zope.security._definitions import thread_local class _Interaction(object): def checkPermission(self, obj, perm): return False obj = object() lhs = self._makeOther({'name': 'view'}) # unauth rhs = self._makeOther({'name': CheckerPublic}) combined = self._makeOne(lhs, rhs) thread_local.interaction = _Interaction() try: combined.check(object(), 'name') #no raise finally: del thread_local.interaction def test_check_lhs_unauth_rhs_forbidden(self): from zope.security.interfaces import Unauthorized from zope.security._definitions import thread_local class _Interaction(object): def checkPermission(self, obj, perm): return False obj = object() lhs = self._makeOther({'name': 'view'}) # unauth rhs = self._makeOther() # forbidden combined = self._makeOne(lhs, rhs) thread_local.interaction = _Interaction() try: self.assertRaises(Unauthorized, combined.check, object(), 'name') finally: del thread_local.interaction def test_check_lhs_unauth_rhs_unauth(self): from zope.security.interfaces import Unauthorized from zope.security._definitions import thread_local class _Interaction(object): def checkPermission(self, obj, perm): return False obj = object() lhs = self._makeOther({'name': 'view'}) # unauth rhs = self._makeOther({'name': 'inspect'}) combined = self._makeOne(lhs, rhs) thread_local.interaction = _Interaction() try: self.assertRaises(Unauthorized, combined.check, object(), 'name') finally: del thread_local.interaction def test_check_lhs_forbidden_rhs_ok(self): from zope.security.checker import CheckerPublic obj = object() lhs = self._makeOther() # forbidden rhs = self._makeOther({'name': CheckerPublic}) combined = self._makeOne(lhs, rhs) combined.check(object(), 'name') # no raise def test_check_lhs_forbidden_rhs_forbidden(self): from zope.security.interfaces import Forbidden obj = object() lhs = self._makeOther() # forbidden rhs = self._makeOther() # forbidden combined = self._makeOne(lhs, rhs) self.assertRaises(Forbidden, combined.check, object(), 'name') def test_check_lhs_forbidden_rhs_unauth(self): from zope.security.interfaces import Unauthorized from zope.security._definitions import thread_local class _Interaction(object): def checkPermission(self, obj, perm): return False obj = object() lhs = self._makeOther() # Forbidden rhs = self._makeOther({'name': 'inspect'}) combined = self._makeOne(lhs, rhs) thread_local.interaction = _Interaction() try: self.assertRaises(Unauthorized, combined.check, object(), 'name') finally: del thread_local.interaction def test_check_setattr_lhs_ok_rhs_not_called(self): from zope.security.checker import CheckerPublic from zope.security.checker import Checker class _NeverCalled(Checker): def check_setattr(self, *args, **kw): raise AssertionError obj = object() lhs = self._makeOther(set_permissions={'name': CheckerPublic}) rhs = _NeverCalled({}) combined = self._makeOne(lhs, rhs) combined.check_setattr(object(), 'name') # no raise def test_check_setattr_lhs_unauth_rhs_ok(self): from zope.security.checker import CheckerPublic from zope.security._definitions import thread_local class _Interaction(object): def checkPermission(self, obj, perm): return False obj = object() lhs = self._makeOther(set_permissions={'name': 'update'}) # unauth rhs = self._makeOther(set_permissions={'name': CheckerPublic}) combined = self._makeOne(lhs, rhs) thread_local.interaction = _Interaction() try: combined.check_setattr(object(), 'name') # no raise finally: del thread_local.interaction def test_check_setattr_lhs_unauth_rhs_forbidden(self): from zope.security.interfaces import Unauthorized from zope.security._definitions import thread_local class _Interaction(object): def checkPermission(self, obj, perm): return False obj = object() lhs = self._makeOther(set_permissions={'name': 'view'}) # unauth rhs = self._makeOther() # forbidden combined = self._makeOne(lhs, rhs) thread_local.interaction = _Interaction() try: self.assertRaises(Unauthorized, combined.check_setattr, object(), 'name') finally: del thread_local.interaction def test_check_setattr_lhs_unauth_rhs_unauth(self): from zope.security.interfaces import Unauthorized from zope.security._definitions import thread_local class _Interaction(object): def checkPermission(self, obj, perm): return False obj = object() lhs = self._makeOther(set_permissions={'name': 'view'}) # unauth rhs = self._makeOther(set_permissions={'name': 'inspect'}) # unauth combined = self._makeOne(lhs, rhs) thread_local.interaction = _Interaction() try: self.assertRaises(Unauthorized, combined.check_setattr, object(), 'name') finally: del thread_local.interaction def test_check_setattr_lhs_forbidden_rhs_ok(self): from zope.security.checker import CheckerPublic obj = object() lhs = self._makeOther() # forbidden rhs = self._makeOther(set_permissions={'name': CheckerPublic}) combined = self._makeOne(lhs, rhs) combined.check_setattr(object(), 'name') # no raise def test_check_setattr_lhs_forbidden_rhs_forbidden(self): from zope.security.interfaces import Forbidden obj = object() lhs = self._makeOther() # forbidden rhs = self._makeOther() # forbidden combined = self._makeOne(lhs, rhs) self.assertRaises(Forbidden, combined.check_setattr, object(), 'name') def test_check_setattr_lhs_forbidden_rhs_unauth(self): from zope.security.interfaces import Unauthorized from zope.security._definitions import thread_local class _Interaction(object): def checkPermission(self, obj, perm): return False obj = object() lhs = self._makeOther() # forbidden rhs = self._makeOther(set_permissions={'name': 'inspect'}) # unauth combined = self._makeOne(lhs, rhs) thread_local.interaction = _Interaction() try: self.assertRaises(Unauthorized, combined.check_setattr, object(), 'name') finally: del thread_local.interaction class CheckerLoggingMixinTests(unittest.TestCase): def _getTargetClass(self): from zope.security.checker import CheckerLoggingMixin return CheckerLoggingMixin def _makeOne(self, raising=None): class _Checker(object): def __init__(self, raising, stream): self._file = stream self._raising = raising def check(self, object, name): if self._raising: raise self._raising check_getattr = check_setattr = check class _Derived(self._getTargetClass(), _Checker): pass return _Derived(raising, self._makeStream()) def _makeStream(self): class _Stream(list): def write(self, msg): self.append(msg) return _Stream() def _makeObject(self): class _Object(object): def __repr__(self): return 'TESTING' return _Object() def test_check_ok_normal_verbosity(self): checker = self._makeOne() checker.check(self._makeObject(), 'name') self.assertEqual(len(checker._file), 0) def test_check_ok_raised_verbosity_available_by_default(self): checker = self._makeOne() checker.verbosity = 2 checker.check(self._makeObject(), '__name__') self.assertEqual(len(checker._file), 1) self.assertEqual(checker._file[0], '[CHK] + Always available: __name__ on TESTING\n') def test_check_ok_raised_verbosity_normal_name(self): checker = self._makeOne() checker.verbosity = 2 checker.check(self._makeObject(), 'name') self.assertEqual(len(checker._file), 1) self.assertEqual(checker._file[0], '[CHK] + Granted: name on TESTING\n') def test_check_unauthorized(self): from zope.security.interfaces import Unauthorized checker = self._makeOne(Unauthorized) self.assertRaises(Unauthorized, checker.check, self._makeObject(), 'name') self.assertEqual(len(checker._file), 1) self.assertEqual(checker._file[0], '[CHK] - Unauthorized: name on TESTING\n') def test_check_unauthorized_raised_verbosity(self): from zope.security.interfaces import Unauthorized checker = self._makeOne(Unauthorized) checker.verbosity = 2 self.assertRaises(Unauthorized, checker.check, self._makeObject(), 'name') self.assertEqual(len(checker._file), 1) self.assertEqual(checker._file[0], '[CHK] - Unauthorized: name on TESTING\n') def test_check_forbidden_attribute(self): from zope.security.interfaces import ForbiddenAttribute checker = self._makeOne(ForbiddenAttribute) self.assertRaises(ForbiddenAttribute, checker.check, self._makeObject(), 'name') self.assertEqual(len(checker._file), 1) self.assertEqual(checker._file[0], '[CHK] - Forbidden: name on TESTING\n') def test_check_getattr_ok_normal_verbosity(self): checker = self._makeOne() checker.check(self._makeObject(), 'name') self.assertEqual(len(checker._file), 0) def test_check_getattr_ok_raised_verbosity_available_by_default(self): checker = self._makeOne() checker.verbosity = 2 checker.check_getattr(self._makeObject(), '__name__') self.assertEqual(len(checker._file), 1) self.assertEqual(checker._file[0], '[CHK] + Always available getattr: ' '__name__ on TESTING\n') def test_check_getattr_ok_raised_verbosity_normal_name(self): checker = self._makeOne() checker.verbosity = 2 checker.check_getattr(self._makeObject(), 'name') self.assertEqual(len(checker._file), 1) self.assertEqual(checker._file[0], '[CHK] + Granted getattr: name on TESTING\n') def test_check_getattr_unauthorized(self): from zope.security.interfaces import Unauthorized checker = self._makeOne(Unauthorized) self.assertRaises(Unauthorized, checker.check_getattr, self._makeObject(), 'name') self.assertEqual(len(checker._file), 1) self.assertEqual(checker._file[0], '[CHK] - Unauthorized getattr: name on TESTING\n') def test_check_getattr_forbidden_attribute(self): from zope.security.interfaces import ForbiddenAttribute checker = self._makeOne(ForbiddenAttribute) self.assertRaises(ForbiddenAttribute, checker.check_getattr, self._makeObject(), 'name') self.assertEqual(len(checker._file), 1) self.assertEqual(checker._file[0], '[CHK] - Forbidden getattr: name on TESTING\n') def test_check_setattr_ok_normal_verbosity(self): checker = self._makeOne() checker.check_setattr(self._makeObject(), 'name') self.assertEqual(len(checker._file), 0) def test_check_setattr_ok_raised_verbosity_normal_name(self): checker = self._makeOne() checker.verbosity = 2 checker.check_setattr(self._makeObject(), 'name') self.assertEqual(len(checker._file), 1) self.assertEqual(checker._file[0], '[CHK] + Granted setattr: name on TESTING\n') def test_check_setattr_unauthorized(self): from zope.security.interfaces import Unauthorized checker = self._makeOne(Unauthorized) self.assertRaises(Unauthorized, checker.check_setattr, self._makeObject(), 'name') self.assertEqual(len(checker._file), 1) self.assertEqual(checker._file[0], '[CHK] - Unauthorized setattr: name on TESTING\n') def test_check_setattr_forbidden_attribute(self): from zope.security.interfaces import ForbiddenAttribute checker = self._makeOne(ForbiddenAttribute) self.assertRaises(ForbiddenAttribute, checker.check_setattr, self._makeObject(), 'name') self.assertEqual(len(checker._file), 1) self.assertEqual(checker._file[0], '[CHK] - Forbidden setattr: name on TESTING\n') def test_check_setitem_unauthorized(self): # __setitem__ is an alias for check_getattr, used for speed reasons # (AFAIU calling tp_setitem from C is much faster than calling a # method by name). from zope.security.interfaces import Unauthorized checker = self._makeOne(Unauthorized) self.assertRaises(Unauthorized, checker.__setitem__, self._makeObject(), 'name') self.assertEqual(len(checker._file), 1) self.assertEqual(checker._file[0], '[CHK] - Unauthorized getattr: name on TESTING\n') class Test__instanceChecker(unittest.TestCase): def setUp(self): from zope.security.checker import _clear _clear() def tearDown(self): from zope.security.checker import _clear _clear() def _callFUT(self, type_): from zope.security.checker import _instanceChecker return _instanceChecker(type_) def test_miss(self): from zope.security.checker import _defaultChecker class Foo(object): pass self.assertTrue(self._callFUT(Foo()) is _defaultChecker) def test_hit(self): from zope.security.checker import _checkers class Foo(object): pass checker = _checkers[Foo] = object() self.assertTrue(self._callFUT(Foo()) is checker) class Test_moduleChecker(unittest.TestCase): def setUp(self): from zope.security.checker import _clear _clear() def tearDown(self): from zope.security.checker import _clear _clear() def _callFUT(self, type_): from zope.security.checker import moduleChecker return moduleChecker(type_) def test_miss(self): from zope.interface import verify self.assertTrue(self._callFUT(verify) is None) def test_hit(self): from zope.interface import verify from zope.security.checker import _checkers checker = _checkers[verify] = object() self.assertTrue(self._callFUT(verify) is checker) class BasicTypesTests(unittest.TestCase): def setUp(self): from zope.security.checker import _clear _clear() def tearDown(self): from zope.security.checker import _clear _clear() def test___setitem__(self): from zope.security.checker import BasicTypes from zope.security.checker import _checkers class Foo(object): pass checker = object() BasicTypes[Foo] = checker self.assertTrue(BasicTypes[Foo] is checker) self.assertTrue(_checkers[Foo] is checker) def test___delitem__(self): from zope.security.checker import BasicTypes from zope.security.checker import _checkers class Foo(object): pass checker = object() BasicTypes[Foo] = checker del BasicTypes[Foo] self.assertFalse(Foo in BasicTypes) self.assertFalse(Foo in _checkers) def test_clear(self): from zope.security.checker import BasicTypes self.assertRaises(NotImplementedError, BasicTypes.clear) def test_update(self): from zope.security.checker import BasicTypes from zope.security.checker import _checkers class Foo(object): pass checker = object() BasicTypes.update({Foo: checker}) self.assertTrue(BasicTypes[Foo] is checker) self.assertTrue(_checkers[Foo] is checker) # Pre-geddon tests start here class Test(unittest.TestCase): def setUp(self): from zope.security.management import newInteraction from zope.security.management import setSecurityPolicy from zope.security.checker import _clear _clear() self.__oldpolicy = setSecurityPolicy(self._makeSecurityPolicy()) newInteraction() def tearDown(self): from zope.security.management import endInteraction from zope.security.management import setSecurityPolicy from zope.security.checker import _clear endInteraction() setSecurityPolicy(self.__oldpolicy) _clear() def _makeSecurityPolicy(self): from zope.interface import implementer from zope.security.interfaces import ISecurityPolicy @implementer(ISecurityPolicy) class SecurityPolicy(object): def checkPermission(self, permission, object): return permission == 'test_allowed' return SecurityPolicy @_skip_if_not_Py2 def test_defineChecker_oldstyle_class(self): import types from zope.security.checker import defineChecker from zope.security.checker import NamesChecker class ClassicClass: __metaclass__ = types.ClassType defineChecker(ClassicClass, NamesChecker()) def test_defineChecker_newstyle_class(self): from zope.security.checker import defineChecker from zope.security.checker import NamesChecker class NewStyleClass: __metaclass__ = type defineChecker(NewStyleClass, NamesChecker()) def test_defineChecker_module(self): import zope.security from zope.security.checker import defineChecker from zope.security.checker import NamesChecker defineChecker(zope.security, NamesChecker()) def test_defineChecker_error(self): from zope.security.checker import defineChecker from zope.security.checker import NamesChecker not_a_type = object() self.assertRaises(TypeError, defineChecker, not_a_type, NamesChecker()) def _makeClasses(self): import types class OldInst: __metaclass__ = types.ClassType a = 1 def b(self): pass c = 2 def gete(self): return 3 e = property(gete) def __getitem__(self, x): return 5, x def __setitem__(self, x, v): pass class NewInst(object, OldInst): # This is not needed, but left in to show the change of metaclass # __metaclass__ = type def gete(self): return 3 def sete(self, v): pass e = property(gete, sete) return OldInst, NewInst # check_getattr cases: # # - no attribute there # - method # - allow and disallow by permission @_skip_if_not_Py2 def test_check_getattr(self): from zope.security.interfaces import Forbidden from zope.security.interfaces import Unauthorized from zope.security.checker import NamesChecker from zope.security.checker import CheckerPublic OldInst, NewInst = self._makeClasses() oldinst = OldInst() oldinst.d = OldInst() newinst = NewInst() newinst.d = NewInst() for inst in oldinst, newinst: checker = NamesChecker(['a', 'b', 'c', '__getitem__'], 'perm') self.assertRaises(Unauthorized, checker.check_getattr, inst, 'a') self.assertRaises(Unauthorized, checker.check_getattr, inst, 'b') self.assertRaises(Unauthorized, checker.check_getattr, inst, 'c') self.assertRaises(Unauthorized, checker.check, inst, '__getitem__') self.assertRaises(Forbidden, checker.check, inst, '__setitem__') self.assertRaises(Forbidden, checker.check_getattr, inst, 'd') self.assertRaises(Forbidden, checker.check_getattr, inst, 'e') self.assertRaises(Forbidden, checker.check_getattr, inst, 'f') checker = NamesChecker(['a', 'b', 'c', '__getitem__'], 'test_allowed') checker.check_getattr(inst, 'a') checker.check_getattr(inst, 'b') checker.check_getattr(inst, 'c') checker.check(inst, '__getitem__') self.assertRaises(Forbidden, checker.check, inst, '__setitem__') self.assertRaises(Forbidden, checker.check_getattr, inst, 'd') self.assertRaises(Forbidden, checker.check_getattr, inst, 'e') self.assertRaises(Forbidden, checker.check_getattr, inst, 'f') checker = NamesChecker(['a', 'b', 'c', '__getitem__'], CheckerPublic) checker.check_getattr(inst, 'a') checker.check_getattr(inst, 'b') checker.check_getattr(inst, 'c') checker.check(inst, '__getitem__') self.assertRaises(Forbidden, checker.check, inst, '__setitem__') self.assertRaises(Forbidden, checker.check_getattr, inst, 'd') self.assertRaises(Forbidden, checker.check_getattr, inst, 'e') self.assertRaises(Forbidden, checker.check_getattr, inst, 'f') @_skip_if_not_Py2 def test_check_setattr(self): from zope.security.interfaces import Forbidden from zope.security.interfaces import Unauthorized from zope.security.checker import Checker from zope.security.checker import CheckerPublic OldInst, NewInst = self._makeClasses() oldinst = OldInst() oldinst.d = OldInst() newinst = NewInst() newinst.d = NewInst() for inst in oldinst, newinst: checker = Checker({}, {'a': 'perm', 'z': 'perm'}) self.assertRaises(Unauthorized, checker.check_setattr, inst, 'a') self.assertRaises(Unauthorized, checker.check_setattr, inst, 'z') self.assertRaises(Forbidden, checker.check_setattr, inst, 'c') self.assertRaises(Forbidden, checker.check_setattr, inst, 'd') self.assertRaises(Forbidden, checker.check_setattr, inst, 'e') self.assertRaises(Forbidden, checker.check_setattr, inst, 'f') checker = Checker({}, {'a': 'test_allowed', 'z': 'test_allowed'}) checker.check_setattr(inst, 'a') checker.check_setattr(inst, 'z') self.assertRaises(Forbidden, checker.check_setattr, inst, 'd') self.assertRaises(Forbidden, checker.check_setattr, inst, 'e') self.assertRaises(Forbidden, checker.check_setattr, inst, 'f') checker = Checker({}, {'a': CheckerPublic, 'z': CheckerPublic}) checker.check_setattr(inst, 'a') checker.check_setattr(inst, 'z') self.assertRaises(Forbidden, checker.check_setattr, inst, 'd') self.assertRaises(Forbidden, checker.check_setattr, inst, 'e') self.assertRaises(Forbidden, checker.check_setattr, inst, 'f') @_skip_if_not_Py2 def test_proxy(self): from zope.security.proxy import getChecker from zope.security.proxy import removeSecurityProxy from zope.security.checker import BasicTypes_examples from zope.security.checker import CheckerPublic from zope.security.checker import NamesChecker OldInst, NewInst = self._makeClasses() checker = NamesChecker(()) rocks = tuple(BasicTypes_examples.values()) for rock in rocks: proxy = checker.proxy(rock) self.assertTrue(proxy is rock, (rock, type(proxy))) for class_ in OldInst, NewInst: inst = class_() for ob in inst, class_: proxy = checker.proxy(ob) self.assertTrue(removeSecurityProxy(proxy) is ob) checker = getChecker(proxy) if ob is inst: self.assertEqual(checker.permission_id('__str__'), None) else: self.assertEqual(checker.permission_id('__str__'), CheckerPublic) #No longer doing anything special for transparent proxies. #A proxy needs to provide its own security checker. # #special = NamesChecker(['a', 'b'], 'test_allowed') #defineChecker(class_, special) # #class TransparentProxy(object): # def __init__(self, ob): # self._ob = ob # # def __getattribute__(self, name): # ob = object.__getattribute__(self, '_ob') # return getattr(ob, name) #for ob in inst, TransparentProxy(inst): # proxy = checker.proxy(ob) # self.assertTrue(removeSecurityProxy(proxy) is ob) # # checker = getChecker(proxy) # self.assertTrue(checker is special, # checker.get_permissions) # # proxy2 = checker.proxy(proxy) # self.assertTrue(proxy2 is proxy, [proxy, proxy2]) def test_iteration(self): from zope.security.checker import ProxyFactory from zope.security.checker import selectChecker for i in ((1,), [1]): _iter = iter(i) proxy = ProxyFactory(_iter, selectChecker(_iter)) self.assertEqual(next(proxy), 1) def testLayeredProxies(self): #Test that a Proxy will not be re-proxied. from zope.security.proxy import Proxy, getObject from zope.security.checker import Checker from zope.security.checker import NamesChecker class Base: __Security_checker__ = NamesChecker(['__Security_checker__']) base = Base() checker = Checker({}) # base is not proxied, so we expect a proxy proxy1 = checker.proxy(base) self.assertTrue(type(proxy1) is Proxy) self.assertTrue(getObject(proxy1) is base) # proxy is a proxy, so we don't expect to get another proxy2 = checker.proxy(proxy1) self.assertTrue(proxy2 is proxy1) self.assertTrue(getObject(proxy2) is base) def testMultiChecker(self): from zope.interface import Interface class I1(Interface): def f1(): '' def f2(): '' class I2(I1): def f3(): '' def f4(): '' class I3(Interface): def g(): '' from zope.exceptions import DuplicationError from zope.security.checker import MultiChecker self.assertRaises(DuplicationError, MultiChecker, [(I1, 'p1'), (I2, 'p2')]) self.assertRaises(DuplicationError, MultiChecker, [(I1, 'p1'), {'f2': 'p2'}]) MultiChecker([(I1, 'p1'), (I2, 'p1')]) checker = MultiChecker([ (I2, 'p1'), {'a': 'p3'}, (I3, 'p2'), (('x','y','z'), 'p4'), ]) self.assertEqual(checker.permission_id('f1'), 'p1') self.assertEqual(checker.permission_id('f2'), 'p1') self.assertEqual(checker.permission_id('f3'), 'p1') self.assertEqual(checker.permission_id('f4'), 'p1') self.assertEqual(checker.permission_id('g'), 'p2') self.assertEqual(checker.permission_id('a'), 'p3') self.assertEqual(checker.permission_id('x'), 'p4') self.assertEqual(checker.permission_id('y'), 'p4') self.assertEqual(checker.permission_id('z'), 'p4') self.assertEqual(checker.permission_id('zzz'), None) def testAlwaysAvailable(self): from zope.security.checker import NamesChecker checker = NamesChecker(()) class C(object): pass self.assertEqual(checker.check(C, '__hash__'), None) self.assertEqual(checker.check(C, '__nonzero__'), None) self.assertEqual(checker.check(C, '__class__'), None) self.assertEqual(checker.check(C, '__implements__'), None) self.assertEqual(checker.check(C, '__lt__'), None) self.assertEqual(checker.check(C, '__le__'), None) self.assertEqual(checker.check(C, '__gt__'), None) self.assertEqual(checker.check(C, '__ge__'), None) self.assertEqual(checker.check(C, '__eq__'), None) self.assertEqual(checker.check(C, '__ne__'), None) self.assertEqual(checker.check(C, '__name__'), None) self.assertEqual(checker.check(C, '__parent__'), None) @_skip_if_not_Py2 def test_setattr(self): from zope.security.interfaces import Forbidden from zope.security.checker import NamesChecker OldInst, NewInst = self._makeClasses() checker = NamesChecker(['a', 'b', 'c', '__getitem__'], 'test_allowed') for inst in NewInst(), OldInst(): self.assertRaises(Forbidden, checker.check_setattr, inst, 'a') self.assertRaises(Forbidden, checker.check_setattr, inst, 'z') # TODO: write a test to see that # Checker.check/check_setattr handle permission # values that evaluate to False def test_ProxyFactory(self): from zope.security.checker import _defaultChecker from zope.security.checker import defineChecker from zope.security.checker import NamesChecker from zope.security.checker import ProxyFactory from zope.security.proxy import getChecker from zope.security.proxy import Proxy class SomeClass(object): pass checker = NamesChecker() specific_checker = NamesChecker() checker_as_magic_attr = NamesChecker() obj = SomeClass() proxy = ProxyFactory(obj) self.assertTrue(type(proxy) is Proxy) self.assertTrue(getChecker(proxy) is _defaultChecker) defineChecker(SomeClass, checker) proxy = ProxyFactory(obj) self.assertTrue(type(proxy) is Proxy) self.assertTrue(getChecker(proxy) is checker) obj.__Security_checker__ = checker_as_magic_attr proxy = ProxyFactory(obj) self.assertTrue(type(proxy) is Proxy) self.assertTrue(getChecker(proxy) is checker_as_magic_attr) proxy = ProxyFactory(obj, specific_checker) self.assertTrue(type(proxy) is Proxy) self.assertTrue(getChecker(proxy) is specific_checker) def test_define_and_undefineChecker(self): from zope.security.checker import defineChecker from zope.security.checker import NamesChecker from zope.security.checker import undefineChecker class SomeClass(object): pass obj = SomeClass() checker = NamesChecker() from zope.security.checker import _defaultChecker, selectChecker self.assertTrue(selectChecker(obj) is _defaultChecker) defineChecker(SomeClass, checker) self.assertTrue(selectChecker(obj) is checker) undefineChecker(SomeClass) self.assertTrue(selectChecker(obj) is _defaultChecker) def test_ProxyFactory_using_proxy(self): from zope.security.checker import ProxyFactory from zope.security.checker import NamesChecker class SomeClass(object): pass obj = SomeClass() checker = NamesChecker() proxy1 = ProxyFactory(obj) proxy2 = ProxyFactory(proxy1) self.assertTrue(proxy1 is proxy2) # Trying to change the checker on a proxy. self.assertRaises(TypeError, ProxyFactory, proxy1, checker) # Setting exactly the same checker as the proxy already has. proxy1 = ProxyFactory(obj, checker) proxy2 = ProxyFactory(proxy1, checker) self.assertTrue(proxy1 is proxy2) def test_canWrite_canAccess(self): # the canWrite and canAccess functions are conveniences. Often code # wants to check if a certain option is open to a user before # presenting it. If the code relies on a certain permission, the # Zope 3 goal of keeping knowledge of security assertions out of the # code and only in the zcml assertions is broken. Instead, ask if the # current user canAccess or canWrite some pertinent aspect of the # object. canAccess is used for both read access on an attribute # and call access to methods. # For example, consider this humble pair of class and object. from zope.security.interfaces import Forbidden from zope.security.checker import Checker from zope.security.checker import canAccess from zope.security.checker import canWrite from zope.security.checker import defineChecker class SomeClass(object): pass obj = SomeClass() # We will establish a checker for the class. This is the standard # name-based checker, and works by specifying two dicts, one for read # and one for write. Each item in the dictionary should be an # attribute name and the permission required to read or write it. # For these tests, the SecurityPolicy defined at the top of this file # is in place. It is a stub. Normally, the security policy would # have knowledge of interactions and participants, and would determine # on the basis of the particpants and the object if a certain permission # were authorized. This stub simply says that the 'test_allowed' # permission is authorized and nothing else is, for any object you pass # it. # Therefore, according to the checker created here, the current # 'interaction' (as stubbed out in the security policy) will be allowed # to access and write foo, and access bar. The interaction is # unauthorized for accessing baz and writing bar. Any other access or # write is not merely unauthorized but forbidden--including write access # for baz. checker = Checker( {'foo':'test_allowed', # these are the read settings 'bar':'test_allowed', 'baz':'you_will_not_have_this_permission'}, {'foo':'test_allowed', # these are the write settings 'bar':'you_will_not_have_this_permission', 'bing':'you_will_not_have_this_permission'}) defineChecker(SomeClass, checker) # so, our hapless interaction may write and access foo... self.assertTrue(canWrite(obj, 'foo')) self.assertTrue(canAccess(obj, 'foo')) # ...may access, but not write, bar... self.assertTrue(not canWrite(obj, 'bar')) self.assertTrue(canAccess(obj, 'bar')) # ...and may access baz. self.assertTrue(not canAccess(obj, 'baz')) # there are no security assertions for writing or reading shazam, so # checking these actually raises Forbidden. The rationale behind # exposing the Forbidden exception is primarily that it is usually # indicative of programming or configuration errors. self.assertRaises(Forbidden, canAccess, obj, 'shazam') self.assertRaises(Forbidden, canWrite, obj, 'shazam') # However, we special-case canWrite when an attribute has a Read # setting but no Write setting. Consider the 'baz' attribute from the # checker above: it is readonly. All users are forbidden to write # it. This is a very reasonable configuration. Therefore, canWrite # will hide the Forbidden exception if and only if there is a # setting for accessing the attribute. self.assertTrue(not canWrite(obj, 'baz')) # The reverse is not true at the moment: an unusal case like the # write-only 'bing' attribute will return a boolean for canWrite, # but canRead will simply raise a Forbidden exception, without checking # write settings. self.assertTrue(not canWrite(obj, 'bing')) self.assertRaises(Forbidden, canAccess, obj, 'bing') class TestCheckerPublic(unittest.TestCase): def test_that_pickling_CheckerPublic_retains_identity(self): from zope.security._compat import _pickle from zope.security.checker import CheckerPublic self.assertTrue(_pickle.loads(_pickle.dumps(CheckerPublic)) is CheckerPublic) def test_that_CheckerPublic_identity_works_even_when_proxied(self): from zope.security.checker import ProxyFactory from zope.security.checker import CheckerPublic self.assertTrue(ProxyFactory(CheckerPublic) is CheckerPublic) class TestMixinDecoratedChecker(unittest.TestCase): def decoratedSetUp(self): from zope.security.management import getInteraction from zope.security.management import newInteraction from zope.security.management import setSecurityPolicy self.policy = self._makeSecurityPolicy() self._oldpolicy = setSecurityPolicy(self.policy) newInteraction() self.interaction = getInteraction() self.obj = object() def decoratedTearDown(self): from zope.security.management import endInteraction from zope.security.management import setSecurityPolicy endInteraction() setSecurityPolicy(self._oldpolicy) def _makeSecurityPolicy(self): from zope.interface import implementer from zope.security.interfaces import ISecurityPolicy @implementer(ISecurityPolicy) class RecordedSecurityPolicy(object): def __init__(self): self._checked = [] self.permissions = {} def checkPermission(self, permission, object): self._checked.append(permission) return self.permissions.get(permission, True) def checkChecked(self, checked): res = self._checked == checked self._checked = [] return res return RecordedSecurityPolicy def check_checking_impl(self, checker): from zope.security.interfaces import ForbiddenAttribute o = self.obj checker.check_getattr(o, 'both_get_set') self.assertTrue(self.interaction.checkChecked(['dc_get_permission'])) checker.check_getattr(o, 'c_only') self.assertTrue(self.interaction.checkChecked(['get_permission'])) checker.check_getattr(o, 'd_only') self.assertTrue(self.interaction.checkChecked(['dc_get_permission'])) self.assertRaises(ForbiddenAttribute, checker.check_getattr, o, 'completely_different_attr') self.assertTrue(self.interaction.checkChecked([])) checker.check(o, '__str__') self.assertTrue(self.interaction.checkChecked(['get_permission'])) checker.check_setattr(o, 'both_get_set') self.assertTrue(self.interaction.checkChecked(['dc_set_permission'])) self.assertRaises(ForbiddenAttribute, checker.check_setattr, o, 'c_only') self.assertTrue(self.interaction.checkChecked([])) self.assertRaises(ForbiddenAttribute, checker.check_setattr, o, 'd_only') self.assertTrue(self.interaction.checkChecked([])) @property def originalChecker(self): from zope.security.checker import NamesChecker return NamesChecker(['both_get_set', 'c_only', '__str__'], 'get_permission') decorationSetMap = {'both_get_set': 'dc_set_permission'} decorationGetMap = {'both_get_set': 'dc_get_permission', 'd_only': 'dc_get_permission'} @property def overridingChecker(self): from zope.security.checker import Checker return Checker(self.decorationGetMap, self.decorationSetMap) class TestCombinedChecker(TestMixinDecoratedChecker, unittest.TestCase): def setUp(self): unittest.TestCase.setUp(self) self.decoratedSetUp() def tearDown(self): self.decoratedTearDown() unittest.TestCase.tearDown(self) def test_checking(self): from zope.security.interfaces import Unauthorized from zope.security.checker import CombinedChecker cc = CombinedChecker(self.overridingChecker, self.originalChecker) self.check_checking_impl(cc) # When a permission is not authorized by the security policy, # the policy is queried twice per check_getattr -- once for each # checker. self.interaction.permissions['dc_get_permission'] = False cc.check_getattr(self.obj, 'both_get_set') self.assertTrue( self.interaction.checkChecked(['dc_get_permission', 'get_permission']) ) # This should raise Unauthorized instead of ForbiddenAttribute, since # access can be granted if you e.g. login with different credentials. self.assertRaises(Unauthorized, cc.check_getattr, self.obj, 'd_only') self.assertRaises(Unauthorized, cc.check, self.obj, 'd_only') def test_interface(self): from zope.interface.verify import verifyObject from zope.security.checker import CombinedChecker from zope.security.interfaces import IChecker dc = CombinedChecker(self.overridingChecker, self.originalChecker) verifyObject(IChecker, dc) class TestBasicTypes(unittest.TestCase): def test(self): from zope.security.checker import BasicTypes from zope.security.checker import NoProxy from zope.security.checker import _checkers from zope.security.checker import _clear class MyType(object): pass class MyType2(object): pass # When an item is added to the basic types, it should also be added to # the list of checkers. BasicTypes[MyType] = NoProxy self.assertTrue(MyType in _checkers) # If we clear the checkers, the type should still be there _clear() self.assertTrue(MyType in BasicTypes) self.assertTrue(MyType in _checkers) # Now delete the type from the dictionary, will also delete it from # the checkers del BasicTypes[MyType] self.assertTrue(MyType not in BasicTypes) self.assertTrue(MyType not in _checkers) # The quick way of adding new types is using update BasicTypes.update({MyType: NoProxy, MyType2: NoProxy}) self.assertTrue(MyType in BasicTypes) self.assertTrue(MyType2 in BasicTypes) self.assertTrue(MyType in _checkers) self.assertTrue(MyType2 in _checkers) # Let's remove the two new types del BasicTypes[MyType] del BasicTypes[MyType2] # Of course, BasicTypes is a full dictionary. This dictionary is by # default filled with several entries: keys = BasicTypes.keys() self.assertTrue(bool in keys) self.assertTrue(int in keys) self.assertTrue(float in keys) self.assertTrue(str in keys) try: unicode except NameError: #pragma NO COVER Py3k pass else: #pragma NO COVER Python2 self.assertTrue(unicode in keys) self.assertTrue(object in keys) # ... # Finally, the ``clear()`` method has been deactivated to avoid # unwanted deletions. self.assertRaises(NotImplementedError, BasicTypes.clear) def test_suite(): return unittest.TestSuite(( unittest.makeSuite(Test_ProxyFactory), unittest.makeSuite(Test_canWrite), unittest.makeSuite(Test_canAccess), unittest.makeSuite(Test_canAccess), unittest.makeSuite(CheckerPyTests), unittest.makeSuite(CheckerTests), unittest.makeSuite(TracebackSupplementTests), unittest.makeSuite(GlobalTests), unittest.makeSuite(Test_NamesChecker), unittest.makeSuite(Test_InterfaceChecker), unittest.makeSuite(Test_MultiChecker), unittest.makeSuite(Test_selectCheckerPy), unittest.makeSuite(Test_selectChecker), unittest.makeSuite(Test_getCheckerForInstancesOf), unittest.makeSuite(Test_defineChecker), unittest.makeSuite(Test_undefineChecker), unittest.makeSuite(CombinedCheckerTests), unittest.makeSuite(CheckerLoggingMixinTests), unittest.makeSuite(Test__instanceChecker), unittest.makeSuite(Test_moduleChecker), unittest.makeSuite(BasicTypesTests), # pre-geddon fossils unittest.makeSuite(Test), unittest.makeSuite(TestCheckerPublic), unittest.makeSuite(TestCombinedChecker), unittest.makeSuite(TestBasicTypes), )) zope.security-4.0.3/src/zope/security/tests/components.py0000664000175000017500000000221312450532147025024 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Components for testing """ from zope.interface import Interface, Attribute, implementer from zope.component import adapter class IAppb(Interface): a = Attribute('test attribute') def f(): "test func" class IApp(IAppb): pass class IContent(Interface): pass @implementer(IContent) class Content(object): pass @adapter(IContent) @implementer(IApp) class Comp(object): def __init__(self, *args): # Ignore arguments passed to constructor pass a = 1 def f(): pass comp = Comp() zope.security-4.0.3/src/zope/security/tests/test_protectclass.py0000664000175000017500000001240112450532147026404 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Test handler for 'protectClass' directive """ import unittest class Test_protectName(unittest.TestCase): def setUp(self): from zope.security.checker import _clear _clear() def tearDown(self): from zope.security.checker import _clear _clear() def _callFUT(self, class_, name, permission): from zope.security.protectclass import protectName return protectName(class_, name, permission) def test_wo_existing_checker_w_zope_Public(self): from zope.security.checker import CheckerPublic from zope.security.checker import _checkers self._callFUT(Foo, 'bar', 'zope.Public') self.assertTrue(_checkers[Foo].get_permissions['bar'] is CheckerPublic) def test_w_existing_checker(self): from zope.security.checker import Checker from zope.security.checker import _checkers checker = _checkers[Foo] = Checker({}) permission = object() self._callFUT(Foo, 'bar', permission) self.assertTrue(_checkers[Foo] is checker) self.assertTrue(checker.get_permissions['bar'] is permission) class Test_protectSetAttribute(unittest.TestCase): def setUp(self): from zope.security.checker import _clear _clear() def tearDown(self): from zope.security.checker import _clear _clear() def _callFUT(self, class_, name, permission): from zope.security.protectclass import protectSetAttribute return protectSetAttribute(class_, name, permission) def test_wo_existing_checker_w_zope_Public(self): from zope.security.checker import CheckerPublic from zope.security.checker import _checkers self._callFUT(Foo, 'bar', 'zope.Public') self.assertTrue(_checkers[Foo].set_permissions['bar'] is CheckerPublic) def test_w_existing_checker(self): from zope.security.checker import Checker from zope.security.checker import _checkers checker = _checkers[Foo] = Checker({}) permission = object() self._callFUT(Foo, 'bar', permission) self.assertTrue(_checkers[Foo] is checker) self.assertTrue(checker.set_permissions['bar'] is permission) class Test_protectLikeUnto(unittest.TestCase): def setUp(self): from zope.security.checker import _clear _clear() def tearDown(self): from zope.security.checker import _clear _clear() def _callFUT(self, class_, like_unto): from zope.security.protectclass import protectLikeUnto return protectLikeUnto(class_, like_unto) def test_wo_existing_like_unto_checker(self): from zope.security.checker import _checkers self.assertFalse(Foo in _checkers) self._callFUT(Bar, Foo) self.assertFalse(Foo in _checkers) self.assertFalse(Bar in _checkers) def test_w_existing_like_unto_checker_wo_existing_checker(self): from zope.security.checker import Checker from zope.security.checker import CheckerPublic from zope.security.checker import defineChecker from zope.security.checker import _checkers permission = object() foo_checker = Checker({'bar': CheckerPublic}, {'bar': permission}) defineChecker(Foo, foo_checker) self._callFUT(Bar, Foo) bar_checker = _checkers[Bar] self.assertEqual(bar_checker.get_permissions, foo_checker.get_permissions) self.assertEqual(bar_checker.set_permissions, foo_checker.set_permissions) def test_w_existing_like_unto_checker_w_existing_checker(self): from zope.security.checker import Checker from zope.security.checker import CheckerPublic from zope.security.checker import defineChecker from zope.security.checker import _checkers permission1, permission2 = object(), object() foo_checker = Checker({'bar': CheckerPublic}, {'bar': permission2}) defineChecker(Foo, foo_checker) bar_checker = Checker({'bar': permission1, 'baz': CheckerPublic}, {}) defineChecker(Bar, bar_checker) self._callFUT(Bar, Foo) bar_checker = _checkers[Bar] self.assertEqual(bar_checker.get_permissions, {'bar': CheckerPublic, 'baz': CheckerPublic}) self.assertEqual(bar_checker.set_permissions, foo_checker.set_permissions) class Foo(object): bar = 'Bar' class Bar(Foo): baz = 'Baz' def test_suite(): return unittest.TestSuite(( unittest.makeSuite(Test_protectName), unittest.makeSuite(Test_protectSetAttribute), unittest.makeSuite(Test_protectLikeUnto), )) zope.security-4.0.3/src/zope/security/tests/test_simpleinteraction.py0000664000175000017500000000532712450532147027440 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Unit tests for zope.security.simpleinteraction. """ import unittest class RequestStub(object): def __init__(self, principal=None): self.principal = principal self.interaction = None class TestInteraction(unittest.TestCase): def test(self): from zope.interface.verify import verifyObject from zope.security.interfaces import IInteraction from zope.security.simplepolicies import ParanoidSecurityPolicy interaction = ParanoidSecurityPolicy() verifyObject(IInteraction, interaction) def test_add(self): from zope.security.simplepolicies import ParanoidSecurityPolicy rq = RequestStub() interaction = ParanoidSecurityPolicy() interaction.add(rq) self.assertTrue(rq in interaction.participations) self.assertTrue(rq.interaction is interaction) # rq already added self.assertRaises(ValueError, interaction.add, rq) interaction2 = ParanoidSecurityPolicy() self.assertRaises(ValueError, interaction2.add, rq) def test_remove(self): from zope.security.simplepolicies import ParanoidSecurityPolicy rq = RequestStub() interaction = ParanoidSecurityPolicy() self.assertRaises(ValueError, interaction.remove, rq) interaction.add(rq) interaction.remove(rq) self.assertTrue(rq not in interaction.participations) self.assertTrue(rq.interaction is None) def testCreateInteraction(self): from zope.interface.verify import verifyObject from zope.security.interfaces import IInteraction from zope.security.simplepolicies import ParanoidSecurityPolicy i1 = ParanoidSecurityPolicy() verifyObject(IInteraction, i1) self.assertEqual(list(i1.participations), []) user = object() request = RequestStub(user) i2 = ParanoidSecurityPolicy(request) verifyObject(IInteraction, i2) self.assertEqual(list(i2.participations), [request]) def test_suite(): return unittest.TestSuite(( unittest.makeSuite(TestInteraction), )) zope.security-4.0.3/src/zope/security/tests/module.py0000664000175000017500000000272112450532147024130 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Preliminaries to hookup a test suite with the external TestModule. This is necessary because the test framework interferes with seeing changes in the running modules via the module namespace. This enables having some subject classes, instances, permissions, etc, that don't live in the test modules, themselves. """ from zope.interface import Interface from zope.schema import Text class I(Interface): def m1(): pass def m2(): pass class I2(I): def m4(): pass class I3(Interface): def m3(): pass class I4(Interface): def m2(): pass class S(Interface): foo = Text() bar = Text() baro = Text(readonly=True) class S2(Interface): foo2 = Text() bar2 = Text() template_bracket = """ %s """ zope.security-4.0.3/src/zope/security/tests/test_zcml.py0000664000175000017500000001742412450532147024655 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2013 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## import unittest class ConformsToIFromUnicode(object): def test_class_conforms_to_IFromUnicode(self): from zope.interface.verify import verifyClass from zope.schema.interfaces import IFromUnicode verifyClass(IFromUnicode, self._getTargetClass()) def test_instance_conforms_to_IFromUnicode(self): from zope.interface.verify import verifyObject from zope.schema.interfaces import IFromUnicode verifyObject(IFromUnicode, self._makeOne()) class PermissionTests(unittest.TestCase, ConformsToIFromUnicode, ): def _getTargetClass(self): from zope.security.zcml import Permission return Permission def _makeOne(self, context=None): if context is None: context = DummyZCMLContext() permission = self._getTargetClass()() permission.context = context return permission def test_fromUnicode_miss(self): permission = self._makeOne() self.assertEqual(permission.fromUnicode('nonesuch.permission'), 'nonesuch.permission') def test_fromUnicode_hit(self): permission = self._makeOne() p_obj = object() permission.context.permission_mapping = {'extant.permission': p_obj} self.assertTrue(permission.fromUnicode('extant.permission') is p_obj) def test__validate_w_public(self): context = DummyZCMLContext() permission = self._makeOne(context) permission._validate('zope.Public') self.assertEqual(len(context._actions), 0) def test__validate_w_non_public(self): from zope.security.permission import checkPermission context = DummyZCMLContext() permission = self._makeOne(context) permission._validate('a.permission') self.assertEqual(len(context._actions), 1) self.assertEqual(context._actions[0]['discriminator'], None) self.assertEqual(context._actions[0]['callable'], checkPermission) self.assertEqual(context._actions[0]['args'], (None, 'a.permission')) class Test_securityPolicy(unittest.TestCase): def _callFUT(self, _context, component): from zope.security.zcml import securityPolicy return securityPolicy(_context, component) def test_it(self): from zope.security.management import setSecurityPolicy context = DummyZCMLContext() component = object() self._callFUT(context, component) self.assertEqual(len(context._actions), 1) self.assertEqual(context._actions[0]['discriminator'], 'defaultPolicy') self.assertEqual(context._actions[0]['callable'], setSecurityPolicy) self.assertEqual(context._actions[0]['args'], (component,)) class Test_permission(unittest.TestCase): def _callFUT(self, _context, id, title, description=None): from zope.security.zcml import permission if description is None: return permission(_context, id, title) return permission(_context, id, title, description) def test_wo_description(self): from zope.component.interface import provideInterface from zope.component.zcml import handler from zope.security.interfaces import IPermission context = DummyZCMLContext() context.info = 'INFO' self._callFUT(context, 'a.permission', 'TITLE') self.assertEqual(len(context._actions), 2) self.assertEqual(context._actions[0]['discriminator'], ('utility', IPermission, 'a.permission')) self.assertEqual(context._actions[0]['callable'], handler) args = context._actions[0]['args'] self.assertEqual(args[0], 'registerUtility') permission = args[1] self.assertEqual(permission.id, 'a.permission') self.assertEqual(permission.title, 'TITLE') self.assertEqual(permission.description, '') self.assertTrue(context._actions[1]['discriminator'] is None) self.assertTrue(context._actions[1]['callable'] is provideInterface) self.assertEqual(context._actions[1]['args'], ('', IPermission)) def test_w_description(self): from zope.component.interface import provideInterface from zope.component.zcml import handler from zope.security.interfaces import IPermission context = DummyZCMLContext() context.info = 'INFO' self._callFUT(context, 'a.permission', 'TITLE', 'DESCRIPTION') self.assertEqual(len(context._actions), 2) self.assertEqual(context._actions[0]['discriminator'], ('utility', IPermission, 'a.permission')) self.assertEqual(context._actions[0]['callable'], handler) args = context._actions[0]['args'] self.assertEqual(args[0], 'registerUtility') permission = args[1] self.assertEqual(permission.id, 'a.permission') self.assertEqual(permission.title, 'TITLE') self.assertEqual(permission.description, 'DESCRIPTION') self.assertTrue(context._actions[1]['discriminator'] is None) self.assertTrue(context._actions[1]['callable'] is provideInterface) self.assertEqual(context._actions[1]['args'], ('', IPermission)) class Test_redefinePermission(unittest.TestCase): def _callFUT(self, _context, from_, to): from zope.security.zcml import redefinePermission return redefinePermission(_context, from_, to) def test_wo_existing_mapping(self): z_context = DummyZCMLContext() class Context(object): pass context = z_context.context = Context() after = object() self._callFUT(z_context, 'before.permission', after) self.assertTrue(context.permission_mapping['before.permission'] is after) def test_w_existing_mapping_wo_existing_key(self): z_context = DummyZCMLContext() class Context(object): pass context = z_context.context = Context() mapping = context.permission_mapping = {} after = object() self._callFUT(z_context, 'before.permission', after) self.assertTrue(context.permission_mapping is mapping) self.assertTrue(context.permission_mapping['before.permission'] is after) def test_w_existing_mapping_w_existing_key(self): z_context = DummyZCMLContext() class Context(object): pass context = z_context.context = Context() mapping = context.permission_mapping = {} before = mapping['before.permission'] = object() after = object() self._callFUT(z_context, 'before.permission', after) self.assertTrue(context.permission_mapping is mapping) self.assertTrue(context.permission_mapping['before.permission'] is after) class DummyZCMLContext(object): def __init__(self): self._actions = [] def action(self, **kw): self._actions.append(kw) def test_suite(): return unittest.TestSuite(( unittest.makeSuite(PermissionTests), unittest.makeSuite(Test_securityPolicy), unittest.makeSuite(Test_permission), unittest.makeSuite(Test_redefinePermission), )) zope.security-4.0.3/src/zope/security/metadirectives.py0000664000175000017500000001541112450532147024511 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Component architecture related 'zope' ZCML namespace directive interfaces """ __docformat__ = 'restructuredtext' import zope.configuration.fields from zope.configuration.fields import GlobalObject, GlobalInterface from zope.configuration.fields import Tokens, PythonIdentifier import zope.interface import zope.schema from zope.interface import Interface import zope.security.zcml from zope.security.i18n import ZopeMessageFactory as _ from zope.security.zcml import Permission from zope.security._compat import _u class IClassDirective(zope.interface.Interface): """Make statements about a class""" class_ = zope.configuration.fields.GlobalObject( title=_("Class"), required=True ) class IImplementsSubdirective(zope.interface.Interface): """Declare that the class given by the content directive's class attribute implements a given interface """ interface = zope.configuration.fields.Tokens( title=_("One or more interfaces"), required=True, value_type=zope.configuration.fields.GlobalInterface() ) class IRequireSubdirective(zope.interface.Interface): """Indicate that the a specified list of names or the names in a given Interface require a given permission for access. """ permission = zope.security.zcml.Permission( title=_("Permission"), description=_(""" Specifies the permission by id that will be required to access or mutate the attributes and methods specified."""), required=False, ) attributes = zope.configuration.fields.Tokens( title=_("Attributes and methods"), description=_("This is a list of attributes and methods" " that can be accessed."), required=False, value_type=zope.configuration.fields.PythonIdentifier(), ) set_attributes = zope.configuration.fields.Tokens( title=_("Attributes that can be set"), description=_("This is a list of attributes that can be" " modified/mutated."), required=False, value_type=zope.configuration.fields.PythonIdentifier(), ) interface = zope.configuration.fields.Tokens( title=_("Interfaces"), description=_("The listed interfaces' methods and attributes" " can be accessed."), required=False, value_type=zope.configuration.fields.GlobalInterface(), ) set_schema = zope.configuration.fields.Tokens( title=_("The attributes specified by the schema can be set"), description=_("The listed schemas' properties can be" " modified/mutated."), required=False, value_type=zope.configuration.fields.GlobalInterface(), ) like_class = zope.configuration.fields.GlobalObject( title=_("Configure like this class"), description=_(""" This argument says that this content class should be configured in the same way the specified class' security is. If this argument is specified, no other argument can be used."""), required=False, ) class IAllowSubdirective(zope.interface.Interface): """ Declare a part of the class to be publicly viewable (that is, requires the zope.Public permission). Only one of the following two attributes may be used. """ attributes = zope.configuration.fields.Tokens( title=_("Attributes"), required=False, value_type=zope.configuration.fields.PythonIdentifier(), ) interface = zope.configuration.fields.Tokens( title=_("Interface"), required=False, value_type=zope.configuration.fields.GlobalInterface(), ) class IFactorySubdirective(zope.interface.Interface): """Specify the factory used to create this content object""" id = zope.schema.Id( title=_("ID"), description=_(""" the identifier for this factory in the ZMI factory identification scheme. If not given, defaults to the literal string given as the content directive's 'class' attribute."""), required=False, ) title = zope.configuration.fields.MessageID( title=_("Title"), description=_("Text suitable for use in the 'add content' menu" " of a management interface"), required=False, ) description = zope.configuration.fields.MessageID( title=_("Description"), description=_("Longer narrative description of what this" " factory does"), required=False, ) class IModule(Interface): """Group security declarations about a module""" module = GlobalObject( title=_u("Module"), description=_u("Pointer to the module object."), required=True) class IAllow(Interface): """Allow access to selected module attributes Access is unconditionally allowed to any names provided directly in the attributes attribute or to any names defined by interfaces listed in the interface attribute. """ attributes = Tokens( title=_u("Attributes"), description=_u("The attributes to provide access to."), value_type = PythonIdentifier(), required=False) interface = Tokens( title=_u("Interface"), description=_u("Interfaces whos names to provide access to. Access " "will be provided to all of the names defined by the " "interface(s). Multiple interfaces can be supplied."), value_type = GlobalInterface(), required=False) class IRequire(Interface): """Require a permission to access selected module attributes The given permission is required to access any names provided directly in the attributes attribute or any names defined by interfaces listed in the interface attribute. """ attributes = Tokens( title=_u("Attributes"), description=_u("The attributes to require permission for."), value_type = PythonIdentifier(), required=False) permission = Permission( title=_u("Permission ID"), description=_u("The id of the permission to require.")) zope.security-4.0.3/src/zope/security/adapter.py0000664000175000017500000001113512450532147023120 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2004 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Support for taking security into account in adaptation """ from zope.security.checker import ProxyFactory from zope.security.proxy import removeSecurityProxy from zope.location import ILocation, LocationProxy def assertLocation(adapter, parent): """Assert locatable adapters. This function asserts that the adapter get location-proxied if it doesn't provide ILocation itself. Further more the returned locatable adapter get its parent set if its __parent__ attribute is currently None. """ # handle none-locatable adapters (A) if not ILocation.providedBy(adapter): locatable = LocationProxy(adapter) locatable.__parent__ = parent return locatable # handle locatable, parentless adapters (B) if adapter.__parent__ is None: adapter.__parent__ = parent return adapter # handle locatable, parentful adapters (C) return adapter class LocatingTrustedAdapterFactory(object): """Adapt an adapter factory to provide trusted and (locatable) adapters. Trusted adapters always adapt unproxied objects. If asked to adapt any proxied objects, it will unproxy them and then security-proxy the resulting adapter (S) unless the objects where not security-proxied before (N). Further locating trusted adapters provide a location for protected adapters only (S). If such a protected adapter itself does not provide ILocation it is wrapped within a location proxy and it parent will be set. If the adapter does provide ILocation and it's __parent__ is None, we set the __parent__ to the adapter's context: """ def __init__(self, factory): self.factory = factory self.__name__ = factory.__name__ self.__module__ = factory.__module__ # protected methods def _customizeProtected(self, adapter, context): return assertLocation(adapter, context) def _customizeUnprotected(self, adapter, context): if (ILocation.providedBy(adapter) and adapter.__parent__ is None): adapter.__parent__ = context return adapter def __call__(self, *args): for arg in args: if removeSecurityProxy(arg) is not arg: args = [removeSecurityProxy(x) for x in args] adapter = self.factory(*args) adapter = self._customizeProtected(adapter, args[0]) return ProxyFactory(adapter) adapter = self.factory(*args) adapter = self._customizeUnprotected(adapter, args[0]) return adapter class TrustedAdapterFactory(LocatingTrustedAdapterFactory): """Adapt an adapter factory to provide trusted adapters. Trusted adapters always adapt unproxied objects. If asked to adapt any proxied objects, it will unproxy them and then security-proxy the resulting adapter unless the objects where not security-proxied before. If the adapter does provide ILocation and it's __parent__ is None, we set the __parent__ to the adapter's context. """ # do not location-proxy the adapter def _customizeProtected(self, adapter, context): return self._customizeUnprotected(adapter, context) class LocatingUntrustedAdapterFactory(object): """Adapt an adapter factory to provide locatable untrusted adapters Untrusted adapters always adapt proxied objects. If any permission other than zope.Public is required, untrusted adapters need a location in order that the local authentication mechanism can be inovked correctly. If the adapter does not provide ILocation, we location proxy it and set the parent. If the adapter does provide ILocation and it's __parent__ is None, we set the __parent__ to the adapter's context only: """ def __init__(self, factory): self.factory = factory self.__name__ = factory.__name__ self.__module__ = factory.__module__ def __call__(self, *args): adapter = self.factory(*args) return assertLocation(adapter, args[0]) zope.security-4.0.3/src/zope/security/_definitions.py0000664000175000017500000000176612450532147024163 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2005 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Common definitions to avoid circular imports """ import threading import zope.interface from zope.security import interfaces from zope.security._compat import _u thread_local = threading.local() @zope.interface.provider(interfaces.IPrincipal) class system_user(object): id = _u('zope.security.management.system_user') title = _u('System') description = _u('') zope.security-4.0.3/src/zope/security/configure.zcml0000664000175000017500000000117712450532147024003 0ustar tseavertseaver00000000000000 zope.security-4.0.3/src/zope/security/examples/0000775000175000017500000000000012533437256022752 5ustar tseavertseaver00000000000000zope.security-4.0.3/src/zope/security/examples/sandbox.py0000664000175000017500000002103012450532147024747 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2003 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """A small sandbox application. """ import time, random from zope.interface import Interface, implementer class IAgent(Interface): """A player/agent in the world. The agent represents an autonomous unit, that lives in various homes/sandboxes and accesses services present at the sandboxes. Agents are imbued with a sense of wanderlust and attempt to find new homes after a few turns of the time generator (think turn based games). """ def action(): """Perform agent's action.""" def setHome(home): """Move to a different home.""" def getHome(): """Return the place where the agent currently lives.""" def getAuthenticationToken(): """Return the authority by which the agent perform actions.""" class IService(Interface): """Marker to designate some form of functionality. Services are available from sandboxes, examples include time service, agent discovery, and sandbox discovery. """ class ISandbox(Interface): """A container for agents to live in and services to be available.""" def getService(service_id): """Get the service having the provided id in this sandbox.""" def getAgents(): """Return a list of agents living in this sandbox.""" def addAgent(agent): """Add a new agent to the sandbox.""" def transportAgent(agent, destination): """Move the specified agent to the destination sandbox.""" class SandboxError(Exception): """A sandbox error is thrown, if any action could not be performed.""" pass class Identity(object): """Mixin for pretty printing and identity method""" def __init__(self, id, *args, **kw): self.id = id def getId(self): return self.id def __str__ (self): return "<%s> %s"%(str(self.__class__.__name__), str(self.id)) __repr__ = __str__ @implementer(IAgent) class Agent(Identity): def __init__(self, id, home, auth_token, action): """Initialize agent.""" self.id = id self.auth_token = auth_token self.home = home self._action = action def action(self): """See IAgent.""" self._action(self, self.getHome()) def setHome(self, home): """See IAgent.""" self.home = home def getHome(self): """See IAgent.""" return self.home def getAuthenticationToken(self): """See IAgent.""" return self.auth_token @implementer(ISandbox) class Sandbox(Identity): """ see ISandbox doc """ def __init__(self, id, service_factories): self.id = id self._services = {} self._agents = {} for sf in service_factories: self.addService(sf()) def getAgentIds(self): return self._agents.keys() def getAgents(self): return self._agents.values() def getServiceIds(self): return self._services.keys() def getService(self, sid): return self._services.get(sid) def getHome(self): return self def addAgent(self, agent): if not self._agents.has_key(agent.getId()) \ and IAgent.providedBy(agent): self._agents[agent.getId()]=agent agent.setHome(self) else: raise SandboxError("couldn't add agent %s"%agent) def addService(self, service): if not self._services.has_key(service.getId()) \ and IService.providedBy(service): self._services[service.getId()]=service service.setHome(self) else: raise SandboxError("couldn't add service %s"%service) def transportAgent(self, agent, destination): if self._agents.has_key(agent.getId()) \ and destination is not self \ and ISandbox.providedBy(destination): destination.addAgent(agent) del self._agents[agent.getId()] else: raise SandboxError("couldn't transport agent %s to %s"%( agent, destination) ) @implementer(IService) class Service(object): def getId(self): return self.__class__.__name__ def setHome(self, home): self._home = home def getHome(self): return getattr(self, '_home') class HomeDiscoveryService(Service): """ returns the ids of available agent homes """ def getAvailableHomes(self): return _homes.keys() class AgentDiscoveryService(Service): """ returns the agents available at a given home """ def getLocalAgents(self, home): return home.getAgents() class TimeService(Service): """ returns the local time """ def getTime(self): return time.time() default_service_factories = ( HomeDiscoveryService, AgentDiscoveryService, TimeService ) def action_find_homes(agent, home): home_service = home.getService('HomeDiscoveryService') return home_service.getAvailableHomes() def action_find_neighbors(agent, home): agent_service = home.getService('AgentDiscoveryService') return agent_service.getLocalAgents(home) def action_find_time(agent, home): time_service = home.getService('TimeService') return time_service.getTime() class TimeGenerator(object): """Represents the passage of time in the agent simulation. each turn represents some discrete unit of time, during which all agents attempt to perform their action. Additionally, all agents are checked to see if they have a desire to move, and if so are transported to a new random home. """ def setupAgent(self, agent): pass def teardownAgent(self, agent): pass def turn(self): global _homes for h in _homes.values(): agents = h.getAgents() for a in agents: self.setupAgent(a) try: a.action() except Exception as e: print('-- Exception --') print('"%s" in "%s" not allow to "%s"' % (a, h, a._action.__name__)) print(e) print() self.teardownAgent(a) agents = filter(WanderLust, agents) for a in agents: self.setupAgent(a) try: home = a.getHome() new_home = GreenerPastures(a) home.transportAgent(a, new_home) except Exception as e: print('-- Exception --') print('moving "%s" from "%s" to "%s"' %(a, h, repr(new_home))) print(e) print() self.teardownAgent(a) def WanderLust(agent): """ is agent ready to move """ if int(random.random()*100) <= 30: return 1 def GreenerPastures(agent): """ where do they want to go today """ global _homes possible_homes = _homes.keys() possible_homes.remove(agent.getHome().getId()) return _homes.get(random.choice(possible_homes)) # boot strap initial setup. # global list of homes _homes = {} all_homes = ( Sandbox('jail', default_service_factories), Sandbox('origin', default_service_factories), Sandbox('valhalla', default_service_factories) ) origin = all_homes[1] for h in all_homes: _homes[h.getId()]=h agents = [ Agent('odin', None, 'norse legend', action_find_time), Agent('loki', None, 'norse legend', action_find_neighbors), Agent('thor', None, 'norse legend', action_find_homes), Agent('thucydides', None, 'greek men', action_find_time), Agent('archimedes', None, 'greek men', action_find_neighbors), Agent('prometheus', None, 'greek men', action_find_homes), ] for a in agents: origin.addAgent(a) def main(): world = TimeGenerator() for x in range(5): print('world turning') world.turn() for h in _homes.values(): print(h.getId(), h.getAgentIds()) if __name__ == '__main__': main() zope.security-4.0.3/src/zope/security/examples/sandbox_security.py0000664000175000017500000001423712450532147026711 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2003 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """A small, secure sandbox application. This module is responsible of securing the sandbox application and run it in a secure mode. There are several steps that are taken to set up the security 1. map permissions to actions 2. map authentication tokens/principals onto permissions 3. implement checker and security policies that affect 1,2 4. bind checkers to classes/instances 5. proxy wrap as necessary """ import sandbox from zope.security.interfaces import IParticipation from zope.security import checker, management, simplepolicies from zope.interface import implementer # Define all permissions that will be available NotAllowed = 'Not Allowed' Public = checker.CheckerPublic TransportAgent = 'Transport Agent' AccessServices = 'Access Services' AccessAgents = 'Access Agents' AccessTimeService = 'Access Time Services' AccessAgentService = 'Access Agent Service' AccessHomeService = 'Access Home Service' AddAgent = 'Add Agent' ALL='All' NoSetAttr = lambda name: NotAllowed class SimulationSecurityDatabase(object): """Security Database In the database, locations are mapped to authentication tokens to permissions. """ origin = { 'any' : [ALL] } jail = { 'norse legend' : [TransportAgent, AccessServices, AccessAgentService, AccessHomeService, TransportAgent, AccessAgents], 'any' : [AccessTimeService, AddAgent] } valhalla = { 'norse legend' : [AddAgent], 'any' : [AccessServices, AccessTimeService, AccessAgentService, AccessHomeService, TransportAgent, AccessAgents] } class SimulationSecurityPolicy(simplepolicies.ParanoidSecurityPolicy): """Security Policy during the Simulation. A very simple security policy that is specific to the simulations. """ def checkPermission(self, permission, object): """See zope.security.interfaces.ISecurityPolicy""" home = object.getHome() db = getattr(SimulationSecurityDatabase, home.getId(), None) if db is None: return False allowed = db.get('any', ()) if permission in allowed or ALL in allowed: return True if not self.participations: return False for participation in self.participations: token = participation.principal.getAuthenticationToken() allowed = db.get(token, ()) if permission not in allowed: return False return True @implementer(IParticipation) class AgentParticipation(object): """Agent Participation during the Simulation. A very simple participation that is specific to the simulations. """ def __init__(self, agent): self.principal = agent self.interaction = None def PermissionMapChecker(permissions_map=None, set_permissions=None): """Create a checker from using the 'permission_map.'""" if permissions_map is None: permissions_map = {} if set_permissions is None: set_permissions = {} res = {} for key, value in permissions_map.items(): for method in value: res[method] = key return checker.Checker(res, set_permissions) ################################# # sandbox security settings sandbox_security = { AccessServices : ['getService', 'addService', 'getServiceIds'], AccessAgents : ['getAgentsIds', 'getAgents'], AddAgent : ['addAgent'], TransportAgent : ['transportAgent'], Public : ['getId','getHome'] } sandbox_checker = PermissionMapChecker(sandbox_security) ################################# # service security settings # time service tservice_security = { AccessTimeService:['getTime'] } time_service_checker = PermissionMapChecker(tservice_security) # home service hservice_security = { AccessHomeService:['getAvailableHomes'] } home_service_checker = PermissionMapChecker(hservice_security) # agent service aservice_security = { AccessAgentService:['getLocalAgents'] } agent_service_checker = PermissionMapChecker(aservice_security) def wire_security(): management.setSecurityPolicy(SimulationSecurityPolicy) checker.defineChecker(sandbox.Sandbox, sandbox_checker) checker.defineChecker(sandbox.TimeService, time_service_checker) checker.defineChecker(sandbox.AgentDiscoveryService, agent_service_checker) checker.defineChecker(sandbox.HomeDiscoveryService, home_service_checker) def addAgent(self, agent): if not self._agents.has_key(agent.getId()) \ and sandbox.IAgent.providedBy(agent): self._agents[agent.getId()]=agent agentChecker = checker.selectChecker(self) wrapped_home = agentChecker.proxy(self) agent.setHome(wrapped_home) else: raise sandbox.SandboxError("couldn't add agent %s" %agent) sandbox.Sandbox.addAgent = addAgent def setupAgent(self, agent): management.newInteraction(AgentParticipation(agent)) sandbox.TimeGenerator.setupAgent = setupAgent def teardownAgent(self, agent): management.endInteraction() sandbox.TimeGenerator.teardownAgent = teardownAgent def GreenerPastures(agent): """ where do they want to go today """ import random _homes = sandbox._homes possible_homes = _homes.keys() possible_homes.remove(agent.getHome().getId()) new_home = _homes.get(random.choice(possible_homes)) return checker.selectChecker(new_home).proxy(new_home) sandbox.GreenerPastures = GreenerPastures if __name__ == '__main__': wire_security() sandbox.main() zope.security-4.0.3/src/zope/security/proxy.py0000664000175000017500000003150512533120566022664 0ustar tseavertseaver00000000000000############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Helper functions for Proxies. """ import functools import sys from zope.proxy import PyProxyBase from zope.security._compat import PYPY from zope.security.interfaces import ForbiddenAttribute def _check_name(meth, wrap_result=True): name = meth.__name__ def _wrapper(self, *args, **kw): wrapped = super(PyProxyBase, self).__getattribute__('_wrapped') checker = super(PyProxyBase, self).__getattribute__('_checker') checker.check(wrapped, name) res = meth(self, *args, **kw) if not wrap_result: return res return checker.proxy(res) return functools.update_wrapper(_wrapper, meth) def _check_name_inplace(meth): name = meth.__name__ def _wrapper(self, *args, **kw): wrapped = super(PyProxyBase, self).__getattribute__('_wrapped') checker = super(PyProxyBase, self).__getattribute__('_checker') checker.check(wrapped, name) w_meth = getattr(wrapped, name, None) if w_meth is not None: # The proxy object cannot change; we are modifying in place. self._wrapped = w_meth(*args, **kw) return self x_name = '__%s__' % name[3:-2] return ProxyPy(getattr(wrapped, x_name)(*args, **kw), checker) return functools.update_wrapper(_wrapper, meth) def _fmt_address(obj): # Try to replicate PyString_FromString("%p", obj), which actually uses # the platform sprintf(buf, "%p", obj), which we cannot access from Python # directly (and ctypes seems like overkill). if sys.platform == 'win32': return '0x%08X' % id(obj) else: return '0x%0x' % id(obj) class ProxyPy(PyProxyBase): __slots__ = ('_wrapped', '_checker') def __new__(cls, value, checker): inst = super(PyProxyBase, cls).__new__(cls) inst._wrapped = value inst._checker = checker return inst def __init__(self, value, checker): if checker is None: raise ValueError('checker may now be None') self._wrapped = value self._checker = checker # Attribute protocol def __getattribute__(self, name): if name in ('_wrapped', '_checker'): # Only allow _wrapped and _checker to be accessed from inside. if sys._getframe(1).f_locals.get('self') is not self: raise AttributeError(name) wrapped = super(PyProxyBase, self).__getattribute__('_wrapped') if name == '_wrapped': return wrapped checker = super(PyProxyBase, self).__getattribute__('_checker') if name == '_checker': return checker if name not in ('__cmp__', '__hash__', '__bool__', '__nonzero__', '__lt__', '__le__', '__eq__', '__ne__', '__ge__', '__gt__'): checker.check_getattr(wrapped, name) if name in ('__reduce__', '__reduce_ex__'): # The superclass specifically denies access to __reduce__ # and __reduce__ex__, not letting proxies be pickled. But # for backwards compatibility, we need to be able to # pickle proxies. See checker:Global for an example. val = getattr(wrapped, name) elif name == '__module__': # The superclass deals with descriptors found in the type # of this object just like the Python language spec states, letting # them have precedence over things found in the instance. This # normally makes us a better proxy implementation. However, the # C version of this code in _proxy doesn't take that same care and instead # uses the generic object attribute access methods directly on # the wrapped object. This is a behaviour difference; so far, it's # only been noticed for the __module__ attribute, which checker:Global # wants to override but couldn't because this object's type's __module__ would # get in the way. That broke pickling, and checker:Global can't return # anything more sophisticated than a str (a tuple) because it gets proxied # and breaks pickling again. Our solution is to match the C version for this # one attribute. val = getattr(wrapped, name) else: val = super(ProxyPy, self).__getattribute__(name) return checker.proxy(val) def __getattr__(self, name): wrapped = super(PyProxyBase, self).__getattribute__('_wrapped') checker = super(PyProxyBase, self).__getattribute__('_checker') checker.check_getattr(wrapped, name) return checker.proxy(getattr(wrapped, name)) def __setattr__(self, name, value): if name in ('_wrapped', '_checker'): return super(PyProxyBase, self).__setattr__(name, value) wrapped = super(PyProxyBase, self).__getattribute__('_wrapped') checker = super(PyProxyBase, self).__getattribute__('_checker') checker.check_setattr(wrapped, name) setattr(wrapped, name, value) def __delattr__(self, name): if name in ('_wrapped', '_checker'): raise AttributeError() wrapped = super(PyProxyBase, self).__getattribute__('_wrapped') checker = super(PyProxyBase, self).__getattribute__('_checker') checker.check_setattr(wrapped, name) delattr(wrapped, name) @_check_name def __getslice__(self, start, end): try: return self._wrapped.__getslice__(start, end) except: getitem = PyProxyBase.__getattribute__(self, '__getitem__') return getitem(slice(start, end)) @_check_name def __setslice__(self, i, j, value): try: return self._wrapped.__setslice__(i, j, value) except: setitem = PyProxyBase.__getattribute__(self, '__setitem__') return setitem(slice(i, j), value) def __cmp__(self, other): # no check wrapped = super(PyProxyBase, self).__getattribute__('_wrapped') return cmp(wrapped, other) def __lt__(self, other): # no check wrapped = super(PyProxyBase, self).__getattribute__('_wrapped') return wrapped < other def __le__(self, other): # no check wrapped = super(PyProxyBase, self).__getattribute__('_wrapped') return wrapped <= other def __eq__(self, other): # no check wrapped = super(PyProxyBase, self).__getattribute__('_wrapped') return wrapped == other def __ne__(self, other): # no check wrapped = super(PyProxyBase, self).__getattribute__('_wrapped') return wrapped != other def __ge__(self, other): # no check wrapped = super(PyProxyBase, self).__getattribute__('_wrapped') return wrapped >= other def __gt__(self, other): # no check wrapped = super(PyProxyBase, self).__getattribute__('_wrapped') return wrapped > other def __hash__(self): # no check wrapped = super(PyProxyBase, self).__getattribute__('_wrapped') return hash(wrapped) def __nonzero__(self): # no check wrapped = super(PyProxyBase, self).__getattribute__('_wrapped') return bool(wrapped) __bool__ = __nonzero__ def __coerce__(self, other): # For some reason _check_name does not work for coerce() wrapped = super(PyProxyBase, self).__getattribute__('_wrapped') checker = super(PyProxyBase, self).__getattribute__('_checker') checker.check(wrapped, '__coerce__') return super(ProxyPy, self).__coerce__(other) def __str__(self): try: return _check_name(PyProxyBase.__str__)(self) except: # The C implementation catches all exceptions. wrapped = super(PyProxyBase, self).__getattribute__('_wrapped') return '' %( wrapped.__class__.__module__, wrapped.__class__.__name__, _fmt_address(wrapped)) def __repr__(self): try: return _check_name(PyProxyBase.__repr__)(self) except: # The C implementation catches all exceptions. wrapped = super(PyProxyBase, self).__getattribute__('_wrapped') return '' %( wrapped.__class__.__module__, wrapped.__class__.__name__, _fmt_address(wrapped)) for name in ['__call__', #'__repr__', #'__str__', '__unicode__', '__reduce__', '__reduce_ex__', #'__lt__', # Unchecked in C proxy (rich coparison) #'__le__', # Unchecked in C proxy (rich coparison) #'__eq__', # Unchecked in C proxy (rich coparison) #'__ne__', # Unchecked in C proxy (rich coparison) #'__ge__', # Unchecked in C proxy (rich coparison) #'__gt__', # Unchecked in C proxy (rich coparison) #'__nonzero__', # Unchecked in C proxy (rich coparison) #'__bool__', # Unchecked in C proxy (rich coparison) #'__hash__', # Unchecked in C proxy (rich coparison) #'__cmp__', # Unchecked in C proxy '__getitem__', '__setitem__', '__delitem__', '__iter__', '__next__', 'next', '__contains__', '__neg__', '__pos__', '__abs__', '__invert__', '__complex__', '__int__', '__float__', '__long__', '__oct__', '__hex__', '__index__', '__add__', '__sub__', '__mul__', '__div__', '__truediv__', '__floordiv__', '__mod__', '__divmod__', '__pow__', '__radd__', '__rsub__', '__rmul__', '__rdiv__', '__rtruediv__', '__rfloordiv__', '__rmod__', '__rdivmod__', '__rpow__', '__lshift__', '__rshift__', '__and__', '__xor__', '__or__', '__rlshift__', '__rrshift__', '__rand__', '__rxor__', '__ror__', ]: meth = getattr(PyProxyBase, name) setattr(ProxyPy, name, _check_name(meth)) for name in ['__len__', ]: meth = getattr(PyProxyBase, name) setattr(ProxyPy, name, _check_name(meth, False)) for name in ['__iadd__', '__isub__', '__imul__', '__idiv__', '__itruediv__', '__ifloordiv__', '__imod__', '__ilshift__', '__irshift__', '__iand__', '__ixor__', '__ior__', '__ipow__', ]: meth = getattr(PyProxyBase, name) setattr(ProxyPy, name, _check_name_inplace(meth)) def getCheckerPy(proxy): return super(PyProxyBase, proxy).__getattribute__('_checker') if PYPY: _builtin_isinstance = __builtins__.isinstance else: _builtin_isinstance = __builtins__['isinstance'] def getObjectPy(proxy): if not _builtin_isinstance(proxy, ProxyPy): return proxy return super(PyProxyBase, proxy).__getattribute__('_wrapped') try: from zope.security._proxy import _Proxy except (ImportError, AttributeError): #pragma NO COVER PyPy / PURE_PYTHON getChecker = getCheckerPy getObject = getObjectPy Proxy = ProxyPy else: #pragma NO COVER CPython from zope.security._proxy import getChecker from zope.security._proxy import getObject Proxy = _Proxy removeSecurityProxy = getObject def getTestProxyItems(proxy): """Return a sorted sequence of checker names and permissions for testing """ checker = getChecker(proxy) return sorted(checker.get_permissions.items()) def isinstance(object, cls): """Test whether an object is an instance of a type. This works even if the object is security proxied. """ # The removeSecurityProxy call is OK here because it is *only* # being used for isinstance return _builtin_isinstance(removeSecurityProxy(object), cls) zope.security-4.0.3/src/zope/security/_zope_security_checker.c0000664000175000017500000004461312450532147026030 0ustar tseavertseaver00000000000000/* Copyright (c) 2004 Zope Foundation and Contributors. All Rights Reserved. This software is subject to the provisions of the Zope Public License, Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. */ #include static PyObject *_checkers, *_defaultChecker, *_available_by_default, *NoProxy; static PyObject *Proxy, *thread_local, *CheckerPublic; static PyObject *ForbiddenAttribute, *Unauthorized; // Compatibility with Python 2 #if PY_MAJOR_VERSION < 3 #define IS_STRING PyString_Check #define MAKE_STRING(name) PyString_AS_STRING(name) #define FROM_STRING PyString_FromString #define FROM_STRING_FORMAT PyString_FromFormat #define INTERN PyString_InternFromString #define MOD_ERROR_VAL #define MOD_SUCCESS_VAL(val) #define MOD_INIT(name) void init##name(void) #define MOD_DEF(ob, name, doc, methods) \ ob = Py_InitModule3(name, methods, doc); #else #define PyInt_FromLong PyLong_FromLong #define IS_STRING PyUnicode_Check #define MAKE_STRING(name) PyBytes_AS_STRING( \ PyUnicode_AsUTF8String(name)) #define FROM_STRING PyUnicode_FromString #define FROM_STRING_FORMAT PyUnicode_FromFormat #define INTERN PyUnicode_InternFromString #define MOD_ERROR_VAL NULL #define MOD_SUCCESS_VAL(val) val #define MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void) #define MOD_DEF(ob, name, doc, methods) \ static struct PyModuleDef moduledef = { \ PyModuleDef_HEAD_INIT, name, doc, -1, methods, }; \ ob = PyModule_Create(&moduledef); #define statichere static #endif #define DECLARE_STRING(N) static PyObject *str_##N DECLARE_STRING(checkPermission); DECLARE_STRING(__Security_checker__); DECLARE_STRING(interaction); #define CLEAR(O) if (O) {PyObject *t = O; O = 0; Py_DECREF(t); } typedef struct { PyObject_HEAD PyObject *getperms, *setperms; } Checker; /* def permission_id(self, name): */ static PyObject * Checker_permission_id(Checker *self, PyObject *name) { /* return self._permission_func(name) */ PyObject *result; if (self->getperms) { result = PyDict_GetItem(self->getperms, name); if (result == NULL) result = Py_None; } else result = Py_None; Py_INCREF(result); return result; } /* def setattr_permission_id(self, name): */ static PyObject * Checker_setattr_permission_id(Checker *self, PyObject *name) { /* return self._setattr_permission_func(name) */ PyObject *result; if (self->setperms) { result = PyDict_GetItem(self->setperms, name); if (result == NULL) result = Py_None; } else result = Py_None; Py_INCREF(result); return result; } static int checkPermission(PyObject *permission, PyObject *object, PyObject *name) { PyObject *interaction, *r; int i; /* if thread_local.interaction.checkPermission(permission, object): */ /* return */ interaction = PyObject_GetAttr(thread_local, str_interaction); if (interaction == NULL) return -1; r = PyObject_CallMethodObjArgs(interaction, str_checkPermission, permission, object, NULL); Py_DECREF(interaction); if (r == NULL) return -1; i = PyObject_IsTrue(r); Py_DECREF(r); if (i < 0) return -1; if (i) return 0; /* else: */ /* __traceback_supplement__ = (TracebackSupplement, object) */ /* raise Unauthorized(object, name, permission) */ r = Py_BuildValue("OOO", object, name, permission); if (r == NULL) return -1; PyErr_SetObject(Unauthorized, r); Py_DECREF(r); return -1; } /* def check(self, object, name): */ /* Note that we have an int version here because we will use it for __setitem__, as described below */ static int Checker_check_int(Checker *self, PyObject *object, PyObject *name) { PyObject *permission=NULL; int operator; /* permission = self._permission_func(name) */ if (self->getperms) permission = PyDict_GetItem(self->getperms, name); /* if permission is not None: */ if (permission != NULL) { /* if permission is CheckerPublic: */ /* return # Public */ if (permission == CheckerPublic) return 0; if (checkPermission(permission, object, name) < 0) return -1; return 0; } operator = (IS_STRING(name) && MAKE_STRING(name)[0] == '_' && MAKE_STRING(name)[1] == '_'); if (operator) { /* elif name in _available_by_default: */ /* return */ int ic = PySequence_Contains(_available_by_default, name); if (ic < 0) return -1; if (ic) return 0; /* if name != '__iter__' or hasattr(object, name): */ /* __traceback_supplement__ = (TracebackSupplement, object) */ /* raise ForbiddenAttribute, (name, object) */ if (strcmp("__iter__", MAKE_STRING(name)) == 0 && ! PyObject_HasAttr(object, name)) /* We want an attr error if we're asked for __iter__ and we don't have it. We'll get one by allowing the access. */ return 0; } { PyObject *args; args = Py_BuildValue("OO", name, object); if (args != NULL) { PyErr_SetObject(ForbiddenAttribute, args); Py_DECREF(args); } return -1; } } /* Here we have the non-int version, implemented using the int version, which is exposed as a method */ static PyObject * Checker_check(Checker *self, PyObject *args) { PyObject *object, *name; if (!PyArg_ParseTuple(args, "OO", &object, &name)) return NULL; if (Checker_check_int(self, object, name) < 0) return NULL; Py_INCREF(Py_None); return Py_None; } /* def check_setattr(self, object, name): */ static PyObject * Checker_check_setattr(Checker *self, PyObject *args) { PyObject *object, *name, *permission=NULL; if (!PyArg_ParseTuple(args, "OO", &object, &name)) return NULL; /* permission = self._permission_func(name) */ if (self->setperms) permission = PyDict_GetItem(self->setperms, name); /* if permission is not None: */ if (permission != NULL) { /* if permission is CheckerPublic: */ /* return # Public */ if (permission != CheckerPublic && checkPermission(permission, object, name) < 0) return NULL; Py_INCREF(Py_None); return Py_None; } /* __traceback_supplement__ = (TracebackSupplement, object) */ /* raise ForbiddenAttribute, (name, object) */ args = Py_BuildValue("OO", name, object); if (args != NULL) { PyErr_SetObject(ForbiddenAttribute, args); Py_DECREF(args); } return NULL; } static PyObject * selectChecker(PyObject *ignored, PyObject *object); /* def proxy(self, value): */ static PyObject * Checker_proxy(Checker *self, PyObject *value) { PyObject *checker, *r; /* if type(value) is Proxy: */ /* return value */ if ((PyObject*)Py_TYPE(value) == Proxy) { Py_INCREF(value); return value; } /* checker = getattr(value, '__Security_checker__', None) */ checker = PyObject_GetAttr(value, str___Security_checker__); /* if checker is None: */ if (checker == NULL) { PyErr_Clear(); /* checker = selectChecker(value) */ checker = selectChecker(NULL, value); if (checker == NULL) return NULL; /* if checker is None: */ /* return value */ if (checker == Py_None) { Py_DECREF(checker); Py_INCREF(value); return value; } } else if (checker == Py_None) { PyObject *errv = Py_BuildValue("sO", "Invalid value, None. " "for security checker", value); if (errv != NULL) { PyErr_SetObject(PyExc_ValueError, errv); Py_DECREF(errv); } return NULL; } r = PyObject_CallFunctionObjArgs(Proxy, value, checker, NULL); Py_DECREF(checker); return r; } /* return Proxy(value, checker) */ static struct PyMethodDef Checker_methods[] = { {"permission_id", (PyCFunction)Checker_permission_id, METH_O, "permission_id(name) -- Return the permission neded to get the name"}, {"setattr_permission_id", (PyCFunction)Checker_setattr_permission_id, METH_O, "setattr_permission_id(name) -- Return the permission neded to set the name" }, {"check_getattr", (PyCFunction)Checker_check, METH_VARARGS, "check_getattr(object, name) -- Check whether a getattr is allowes"}, {"check_setattr", (PyCFunction)Checker_check_setattr, METH_VARARGS, "check_setattr(object, name) -- Check whether a setattr is allowes"}, {"check", (PyCFunction)Checker_check, METH_VARARGS, "check(object, opname) -- Check whether an operation is allowes"}, {"proxy", (PyCFunction)Checker_proxy, METH_O, "proxy(object) -- Security-proxy an object"}, {NULL, NULL} /* sentinel */ }; static int Checker_clear(Checker *self) { CLEAR(self->getperms); CLEAR(self->setperms); return 0; } static void Checker_dealloc(Checker *self) { Checker_clear(self); Py_TYPE(self)->tp_free((PyObject*)self); } static int Checker_traverse(Checker *self, visitproc visit, void *arg) { if (self->getperms != NULL && visit(self->getperms, arg) < 0) return -1; if (self->setperms != NULL && visit(self->setperms, arg) < 0) return -1; return 0; } static int Checker_init(Checker *self, PyObject *args, PyObject *kwds) { PyObject *getperms, *setperms=NULL; static char *kwlist[] = {"get_permissions", "set_permissions", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O!|O!:Checker", kwlist, &PyDict_Type, &getperms, &PyDict_Type, &setperms)) return -1; Py_INCREF(getperms); self->getperms = getperms; Py_XINCREF(setperms); self->setperms = setperms; return 0; } static PyObject * Checker_get_get_permissions(Checker *self, void *closure) { if (self->getperms == NULL) { self->getperms = PyDict_New(); if (self->getperms == NULL) return NULL; } Py_INCREF(self->getperms); return self->getperms; } static PyObject * Checker_get_set_permissions(Checker *self, void *closure) { if (self->setperms == NULL) { self->setperms = PyDict_New(); if (self->setperms == NULL) return NULL; } Py_INCREF(self->setperms); return self->setperms; } static PyGetSetDef Checker_getset[] = { {"get_permissions", (getter)Checker_get_get_permissions, NULL, "getattr name to permission dictionary", NULL}, {"set_permissions", (getter)Checker_get_set_permissions, NULL, "setattr name to permission dictionary", NULL}, {NULL} /* Sentinel */ }; /* We create operator aliases for check and proxy. Why? Because calling operator slots is much faster than calling methods and security checks are done so often that speed matters. So we have this hack of using almost-arbitrary operations to represent methods that we call alot. The security proxy implementation participates in the same hack. */ static PyMappingMethods Checker_as_mapping = { /* mp_length */ NULL, /* mp_subscript */ (binaryfunc)Checker_proxy, /* mp_ass_subscript */ (objobjargproc)Checker_check_int, }; static PyTypeObject CheckerType = { PyVarObject_HEAD_INIT(NULL, 0) "zope.security.checker.Checker", sizeof(Checker), 0, /* tp_itemsize */ (destructor)&Checker_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ &Checker_as_mapping, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */ "Security checker", /* tp_doc */ (traverseproc)Checker_traverse, /* tp_traverse */ (inquiry)Checker_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Checker_methods, /* tp_methods */ 0, /* tp_members */ Checker_getset, /* tp_getset */ 0, /* tp_base */ 0, /* internal use */ /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)Checker_init, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* Low-level free-mem routine */ /* tp_free */ 0, /* For PyObject_IS_GC */ /* tp_is_gc */ }; /* def selectChecker(object): */ /* """Get a checker for the given object */ /* The appropriate checker is returned or None is returned. If the */ /* return value is None, then object should not be wrapped in a proxy. */ /* """ */ static char selectChecker_doc[] = "Get a checker for the given object\n" "\n" "The appropriate checker is returned or None is returned. If the\n" "return value is None, then object should not be wrapped in a proxy.\n" ; static PyObject * selectChecker(PyObject *ignored, PyObject *object) { PyObject *checker; /* checker = _getChecker(type(object), _defaultChecker) */ checker = PyDict_GetItem(_checkers, (PyObject*)Py_TYPE(object)); if (checker == NULL) checker = _defaultChecker; /* if checker is NoProxy: */ /* return None */ if (checker == NoProxy) { Py_INCREF(Py_None); return Py_None; } /* if checker is _defaultChecker and isinstance(object, Exception): */ /* return None */ if (checker == _defaultChecker && PyObject_IsInstance(object, PyExc_Exception)) { Py_INCREF(Py_None); return Py_None; } /* while not isinstance(checker, Checker): */ /* checker = checker(object) */ /* if checker is NoProxy or checker is None: */ /* return None */ Py_INCREF(checker); while (! PyObject_TypeCheck(checker, &CheckerType)) { PyObject *newchecker; newchecker = PyObject_CallFunctionObjArgs(checker, object, NULL); Py_DECREF(checker); if (newchecker == NULL) return NULL; checker = newchecker; if (checker == NoProxy || checker == Py_None) { Py_DECREF(checker); Py_INCREF(Py_None); return Py_None; } } /* return checker */ return checker; } static char module___doc__[] = "C optimizations for zope.security.checker"; static PyMethodDef module_functions[] = { {"selectChecker", (PyCFunction)selectChecker, METH_O, selectChecker_doc}, {NULL} /* Sentinel */ }; MOD_INIT(_zope_security_checker) { PyObject* m; PyObject* mod; MOD_DEF(mod, "_zope_security_checker", module___doc__, module_functions) if (mod == NULL) { return MOD_ERROR_VAL; } CheckerType.tp_new = PyType_GenericNew; if (PyType_Ready(&CheckerType) < 0) { return MOD_ERROR_VAL; } _defaultChecker = PyObject_CallFunction((PyObject*)&CheckerType, "{}"); if (_defaultChecker == NULL) { return MOD_ERROR_VAL; } #define INIT_STRING(S) \ if((str_##S = INTERN(#S)) == NULL) return MOD_ERROR_VAL INIT_STRING(checkPermission); INIT_STRING(__Security_checker__); INIT_STRING(interaction); if ((_checkers = PyDict_New()) == NULL) { return MOD_ERROR_VAL; } NoProxy = PyObject_CallObject((PyObject*)&PyBaseObject_Type, NULL); if (NoProxy == NULL) { return MOD_ERROR_VAL; } if ((m = PyImport_ImportModule("zope.security._proxy")) == NULL) { return MOD_ERROR_VAL; } if ((Proxy = PyObject_GetAttrString(m, "_Proxy")) == NULL) { return MOD_ERROR_VAL; } Py_DECREF(m); if ((m = PyImport_ImportModule("zope.security._definitions")) == NULL) { return MOD_ERROR_VAL; } thread_local = PyObject_GetAttrString(m, "thread_local"); if (thread_local == NULL) { return MOD_ERROR_VAL; } Py_DECREF(m); if ((m = PyImport_ImportModule("zope.security.interfaces")) == NULL) { return MOD_ERROR_VAL; } ForbiddenAttribute = PyObject_GetAttrString(m, "ForbiddenAttribute"); if (ForbiddenAttribute == NULL) { return MOD_ERROR_VAL; } Unauthorized = PyObject_GetAttrString(m, "Unauthorized"); if (Unauthorized == NULL) { return MOD_ERROR_VAL; } Py_DECREF(m); if ((m = PyImport_ImportModule("zope.security.checker")) == NULL) { return MOD_ERROR_VAL; } CheckerPublic = PyObject_GetAttrString(m, "CheckerPublic"); if (CheckerPublic == NULL) { return MOD_ERROR_VAL; } Py_DECREF(m); if ((_available_by_default = PyList_New(0)) == NULL) { return MOD_ERROR_VAL; } #define EXPORT(N) Py_INCREF(N); PyModule_AddObject(mod, #N, N) EXPORT(_checkers); EXPORT(NoProxy); EXPORT(_defaultChecker); EXPORT(_available_by_default); Py_INCREF(&CheckerType); PyModule_AddObject(mod, "Checker", (PyObject *)&CheckerType); return MOD_SUCCESS_VAL(mod); } zope.security-4.0.3/src/zope/security/permissions.zcml0000664000175000017500000000177312450532147024377 0ustar tseavertseaver00000000000000 zope.security-4.0.3/COPYRIGHT.txt0000664000175000017500000000004012450532147017615 0ustar tseavertseaver00000000000000Zope Foundation and Contributorszope.security-4.0.3/CHANGES.rst0000664000175000017500000003173312533437177017334 0ustar tseavertseaver00000000000000Changes ======= 4.0.3 (2015-06-02) ------------------ - Fix iteration over security proxies in Python 3 using the pure-Python implementation. 4.0.2 (2015-06-02) ------------------ - Fix compatibility with ``zope.proxy`` 4.1.5 under PyPy. - Fix the very first call to ``removeSecurityProxy`` returning incorrect results if given a proxy under PyPy. 4.0.1 (2014-03-19) ------------------ - Add support for Python 3.4. 4.0.0 (2013-07-09) ------------------ - Update ``boostrap.py`` to version 2.2. - Bugfix: ZOPE_WATCH_CHECKERS=2 used to incorrectly suppress unauthorized/forbidden warnings. - Bugfix: ZOPE_WATCH_CHECKERS=1 used to miss most of the checks. 4.0.0b1 (2013-03-11) -------------------- - Add support for PyPy. - Fix extension compilation on windows python 3.x 4.0.0a5 (2013-02-28) -------------------- - Undo changes from 4.0.0a4. Instead, ``zope.untrustedpython`` is only included during Python 2 installs. 4.0.0a4 (2013-02-28) -------------------- - Remove ``untrustedpython`` extra again, since we do not want to support ``zope.untrustedpython`` in ZTK 2.0. If BBB is really needed, we will create a 3.10.0 release. 4.0.0a3 (2013-02-15) -------------------- - Fix test breakage in 4.0.0a2 due to deprecation strategy. 4.0.0a2 (2013-02-15) -------------------- - Add back the ``untrustedpython`` extra: now pulls in ``zope.untrustedpython``. Restored deprecated backward-compatible imports for ``zope.security.untrustedpython.{builtins,interpreter,rcompile}`` (the extra and the imports are to be removed in version 4.1). 4.0.0a1 (2013-02-14) -------------------- - Add support for Python 3.2 and 3.3. - Bring unit test coverage to 100%. - ``zope.security.untrustedpython`` moved to separate project: ``zope.untrustedpython`` - Convert use of ``assert`` in non-test code to apprpriate error types: - Non-dict's passed to ``Checker.__init__``. - Remove dprecattion of ``zope.security.adapter.TrustedAdapterFactory``. Although it has been marked as deprectaed since before Zope3 3.2, current versions of ``zope.compoent`` still rely on it. - Convert doctests to Sphinx documentation in 'docs'. - Add ``setup.py docs`` alias (installs ``Sphinx`` and dependencies). - Add ``setup.py dev`` alias (runs ``setup.py develop`` plus installs ``nose`` and ``coverage``). - Make non-doctest tests fully independent of ``zope.testing``. Two modules, ``zope.security.checker`` and ``zope.security.management``, register cleanups with ``zope.testing`` IFF it is importable, but the tests no longer rely on it. - Enable building extensions without the ``svn:external`` of the ``zope.proxy`` headers into our ``include`` dir. - Bump ``zope.proxy`` dependency to ">= 4.1.0" to enable compilation on Py3k. - Replace deprecated ``zope.component.adapts`` usage with equivalent ``zope.component.adapter`` decorator. - Replace deprecated ``zope.interface.classProvides`` usage with equivalent ``zope.interface.provider`` decorator. - Replace deprecated ``zope.interface.implements`` usage with equivalent ``zope.interface.implementer`` decorator. - Drop support for Python 2.4 and 2.5. - Add test convenience helper ``create_interaction`` and ``with interaction()``. 3.9.0 (2012-12-21) ------------------ - Pin ``zope.proxy >= 4.1.0`` - Ship with an included ``proxy.h`` header which is compatible with the 4.1.x version ov ``zope.proxy``. 3.8.5 (2012-12-21) ------------------ - Ship with an included ``proxy.h`` header which is compatible with the supported versions of ``zope.proxy``. 3.8.4 (2012-12-20) ------------------ - Pin ``zope.proxy >= 3.4.2, <4.1dev`` 3.8.3 (2011-09-24) ------------------ - Fix a regression introduced in 3.8.1: ``zope.location``\'s LocationProxy did not get a security checker if ``zope.security.decorator`` was not imported manually. Now ``zope.security.decorator`` is imported in ``zope.security.proxy`` without re-introducing the circular import fixed in 3.8.1. 3.8.2 (2011-05-24) ------------------ - Fix a test that failed on Python 2.7. 3.8.1 (2011-05-03) ------------------ - Fix circular import beween ``zope.security.decorator`` and ``zope.security.proxy`` which led to an ``ImportError`` when only importing ``zope.security.decorator``. 3.8.0 (2010-12-14) ------------------ - Add tests for our own ``configure.zcml``. - Add ``zcml`` extra dependencies; run related tests only if ``zope.configuration`` is available. - Run tests related to the ``untrustedpython`` functionality only if ``RestrictedPython`` is available. 3.7.3 (2010-04-30) ------------------ - Prefer the standard library's ``doctest`` module to the one from ``zope.testing``. - Ensure ``PermissionIdsVocabulary`` directly provides ``IVocabularyFactory``, even though it might be unnecessary because ``IVocabularyFactory`` is provided in ZCML. - Remove the dependency on the zope.exceptions package: zope.security.checker now imports ``DuplicationError`` from zope.exceptions if available, otherwise it defines a package-specific ``DuplicationError`` class which inherits from Exception. 3.7.2 (2009-11-10) ------------------ - Add compatibility with Python 2.6 abstract base classes. 3.7.1 (2009-08-13) ------------------ - Fix for LP bug 181833 (from Gustavo Niemeyer). Before "visiting" a sub-object, a check should be made to ensure the object is still valid. Because garbage collection may involve loops, if you garbage collect an object, it is possible that the actions done on this object may modify the state of other objects. This may cause another round of garbage collection, eventually generating a segfault (see LP bug). The Py_VISIT macro does the necessary checks, so it is used instead of the previous code. 3.7.0 (2009-05-13) ------------------ - Make ``pytz`` a soft dependency: the checker for ``pytz.UTC`` is created / tested only if the package is already present. Run ``bin/test_pytz`` to run the tests with ``pytz`` on the path. 3.6.3 (2009-03-23) ------------------ - Ensure that simple zope.schema's ``VocabularyRegistry`` is used for ``PermissionVocabulary`` tests, because it's replaced implicitly in environments with ``zope.app.schema`` installed that makes that tests fail. - Fix a bug in ``DecoratedSecurityCheckerDescriptor`` which made security-wrapping location proxied exception instances throw exceptions on Python 2.5. See https://bugs.launchpad.net/zope3/+bug/251848 3.6.2 (2009-03-14) ------------------ - Add ``zope.i18nmessageid.Message`` to non-proxied basic types. It's okay, because messages are immutable. Done previously by ``zope.app.security``. - Add ``__name__`` and ``__parent__`` attributes to list of available by default. Done previously by ``zope.app.security``. - Move ``PermissionsVocabulary`` and ``PermissionIdsVocabulary`` vocabularies to the ``zope.security.permission`` module from the ``zope.app.security`` package. - Add zcml permission definitions for most common and useful permissions, like ``zope.View`` and ``zope.ManageContent``, as well as for the special ``zope.Public`` permission. They are placed in a separate ``permissions.zcml`` file, so it can be easily excluded/redefined. They are selected part of permissions moved from ``zope.app.security`` and used by many ``zope.*`` packages. - Add ``addCheckerPublic`` helper function in ``zope.security.testing`` module that registers the "zope.Public" permission as an IPermission utility. - Add security declarations for the ``zope.security.permisson.Permission`` class. - Improve test coverage. 3.6.1 (2009-03-10) ------------------ - Use ``from`` imports instead of ``zope.deferred`` to avoid circular import problems, thus drop dependency on ``zope.deferredimport``. - Raise ``NoInteraction`` when ``zope.security.checkPermission`` is called without interaction being active (LP #301565). - Don't define security checkers for deprecated set types from the "sets" module on Python 2.6. It's discouraged to use them and ``set`` and ``frozenset`` built-in types should be used instead. - Change package's mailng list address to zope-dev at zope.org as zope3-dev at zope.org is now retired. - Remove old zpkg-related files. 3.6.0 (2009-01-31) ------------------ - Install decorated security checker support on ``LocationProxy`` from the outside. - Add support to bootstrap on Jython. - Move the ``protectclass`` module from ``zope.app.security`` to this package to reduce the number of dependencies on ``zope.app.security``. - Move the ```` directive implementation from ``zope.app.security`` to this package. - Move the ```` directive implementation from ``zope.app.component`` to this package. 3.5.2 (2008-07-27) ------------------ - Make C code compatible with Python 2.5 on 64bit architectures. 3.5.1 (2008-06-04) ------------------ - Add ``frozenset``, ``set``, ``reversed``, and ``sorted`` to the list of safe builtins. 3.5.0 (2008-03-05) ------------------ - Changed title for ``zope.security.management.system_user`` to be more presentable. 3.4.3 - (2009/11/26) -------------------- - Backport a fix made by Gary Poster to the 3.4 branch: Fix for LP bug 181833 (from Gustavo Niemeyer). Before "visiting" a sub-object, a check should be made to ensure the object is still valid. Because garbage collection may involve loops, if you garbage collect an object, it is possible that the actions done on this object may modify the state of other objects. This may cause another round of garbage collection, eventually generating a segfault (see LP bug). The ``Py_VISIT`` macro does the necessary checks, so it is used instead of the previous code. 3.4.2 - (2009/03/23) -------------------- - Add dependency on ``zope.thread`` to setup.py; without it, the tests were failing. - Backport a fix made by Albertas Agejevas to the 3.4 branch. He fixed a bug in DecoratedSecurityCheckerDescriptor which made security-wrapping location proxied exception instances throw exceptions on Python 2.5. See https://bugs.launchpad.net/zope3/+bug/251848 3.4.1 - 2008/07/27 ------------------ - Make C code compatible with Python 2.5 on 64bit architectures. 3.4.0 (2007-10-02) ------------------ - Update meta-data. 3.4.0b5 (2007-08-15) -------------------- - Fix a circular import in the C implementation. 3.4.0b4 (2007-08-14) -------------------- - Improve ugly/brittle ID of ``zope.security.management.system_user``. 3.4.0b3 (2007-08-14) -------------------- - Add support for Python 2.5. - Bug: ``zope.security.management.system_user`` wasn't a valid principal (didn't provide IPrincipal). - Bug: Fix inclusion of doctest to use the doctest module from ``zope.testing``. Now tests can be run multiple times without breaking. (#98250) 3.4.0b2 (2007-06-15) -------------------- - Bug: Remove stack extraction in ``newInteraction``. When using eggs this is an extremly expensive function. The publisher is now more than 10 times faster when using eggs and about twice as fast with a zope trunk checkout. 3.4.0b1 ------- - Temporarily fixed the hidden (and accidental) dependency on zope.testing to become optional. Note: The releases between 3.2.0 and 3.4.0b1 where not tracked as an individual package and have been documented in the Zope 3 changelog. 3.2.0 (2006-01-05) ------------------ - Corresponds to the verison of the ``zope.security`` package shipped as part of the Zope 3.2.0 release. - Remove deprecated helper functions, ``proxy.trustedRemoveSecurityProxy`` and ``proxy.getProxiedObject``. - Make handling of ``management.{end,restore}Interaction`` more careful w.r.t. edge cases. - Make behavior of ``canWrite`` consistent with ``canAccess``: if ``canAccess`` does not raise ``ForbiddenAttribute``, then neither will ``canWrite``. See: http://www.zope.org/Collectors/Zope3-dev/506 - Code style / documentation / test fixes. 3.1.0 (2005-10-03) ------------------ - Add support for use of the new Python 2.4 datatypes, ``set`` and ``frozenset``, within checked code. - Make the C security proxy depend on the ``proxy.h`` header from the ``zope.proxy`` package. - XXX: the spelling of the ``#include`` is bizarre! It seems to be related to ``zpkg``-based builds, and should likely be revisited. For the moment, I have linked in the ``zope.proxy`` package into our own ``include`` directory. See the subversion checkin: http://svn.zope.org/Zope3/?rev=37882&view=rev - Update checker to avoid re-proxying objects which have and explicit ``__Security_checker__`` assigned. - Corresponds to the verison of the ``zope.security`` package shipped as part of the Zope 3.1.0 release. - Clarify contract of ``IChecker`` to indicate that its ``check*`` methods may raise only ``Forbidden`` or ``Unauthorized`` exceptions. - Add interfaces, (``IPrincipal``, ``IGroupAwarePrincipal``, ``IGroup``, and ``IPermission``) specifying contracts of components in the security framework. - Code style / documentation / test fixes. 3.0.0 (2004-11-07) ------------------ - Corresponds to the version of the ``zope.security`` package shipped as part of the Zope X3.0.0 release. zope.security-4.0.3/LICENSE.txt0000664000175000017500000000402612450532147017337 0ustar tseavertseaver00000000000000Zope Public License (ZPL) Version 2.1 A copyright notice accompanies this license document that identifies the copyright holders. This license has been certified as open source. It has also been designated as GPL compatible by the Free Software Foundation (FSF). Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions in source code must retain the accompanying copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the accompanying copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Names of the copyright holders must not be used to endorse or promote products derived from this software without prior written permission from the copyright holders. 4. The right to distribute this software or to use it for any purpose does not give you the right to use Servicemarks (sm) or Trademarks (tm) of the copyright holders. Use of them is covered by separate agreement with the copyright holders. 5. If any files are modified, you must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. Disclaimer THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. zope.security-4.0.3/README.rst0000664000175000017500000000115512462242077017206 0ustar tseavertseaver00000000000000``zope.security`` ================= .. image:: https://pypip.in/version/zope.security/badge.svg?style=flat :target: https://pypi.python.org/pypi/zope.security/ :alt: Latest Version .. image:: https://travis-ci.org/zopefoundation/zope.security.png?branch=master :target: https://travis-ci.org/zopefoundation/zope.security .. image:: https://readthedocs.org/projects/zopesecurity/badge/?version=latest :target: http://zopesecurity.readthedocs.org/en/latest/ :alt: Documentation Status The Security framework provides a generic mechanism to implement security policies on Python objects. zope.security-4.0.3/docs/0000775000175000017500000000000012533437256016451 5ustar tseavertseaver00000000000000zope.security-4.0.3/docs/make.bat0000664000175000017500000001176412450532147020060 0ustar tseavertseaver00000000000000@ECHO OFF REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR=_build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . set I18NSPHINXOPTS=%SPHINXOPTS% . if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. singlehtml to make a single large HTML file echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. text to make text files echo. man to make manual pages echo. texinfo to make Texinfo files echo. gettext to make PO message catalogs echo. changes to make an overview over all changed/added/deprecated items echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\zopesecurity.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\zopesecurity.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp if errorlevel 1 exit /b 1 echo. echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub if errorlevel 1 exit /b 1 echo. echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex if errorlevel 1 exit /b 1 echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text if errorlevel 1 exit /b 1 echo. echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man if errorlevel 1 exit /b 1 echo. echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "texinfo" ( %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo if errorlevel 1 exit /b 1 echo. echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. goto end ) if "%1" == "gettext" ( %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale if errorlevel 1 exit /b 1 echo. echo.Build finished. The message catalogs are in %BUILDDIR%/locale. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes if errorlevel 1 exit /b 1 echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck if errorlevel 1 exit /b 1 echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest if errorlevel 1 exit /b 1 echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) :end zope.security-4.0.3/docs/Makefile0000664000175000017500000001272412450532147020110 0ustar tseavertseaver00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/zopesecurity.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/zopesecurity.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/zopesecurity" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/zopesecurity" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." zope.security-4.0.3/docs/_static/0000775000175000017500000000000012533437256020077 5ustar tseavertseaver00000000000000zope.security-4.0.3/docs/_static/.gitignore0000664000175000017500000000000012460222652022044 0ustar tseavertseaver00000000000000zope.security-4.0.3/docs/api/0000775000175000017500000000000012533437256017222 5ustar tseavertseaver00000000000000zope.security-4.0.3/docs/api/decorator.rst0000664000175000017500000001220712450532147021731 0ustar tseavertseaver00000000000000:mod:`zope.security.decorator` =============================== .. testsetup:: from zope.component.testing import setUp setUp() .. autoclass:: zope.security.decorator.DecoratedSecurityCheckerDescriptor :members: :member-order: bysource To illustrate, we'll create a class that will be proxied: .. doctest:: >>> class Foo(object): ... a = 'a' and a class to proxy it that uses a decorated security checker: .. doctest:: >>> from zope.security.decorator import DecoratedSecurityCheckerDescriptor >>> from zope.proxy import ProxyBase >>> class Wrapper(ProxyBase): ... b = 'b' ... __Security_checker__ = DecoratedSecurityCheckerDescriptor() Next we'll create and register a checker for `Foo`: .. doctest:: >>> from zope.security.checker import NamesChecker, defineChecker >>> fooChecker = NamesChecker(['a']) >>> defineChecker(Foo, fooChecker) along with a checker for `Wrapper`: .. doctest:: >>> wrapperChecker = NamesChecker(['b']) >>> defineChecker(Wrapper, wrapperChecker) Using `selectChecker()`, we can confirm that a `Foo` object uses `fooChecker`: .. doctest:: >>> from zope.security.checker import selectChecker >>> from zope.security.interfaces import ForbiddenAttribute >>> foo = Foo() >>> selectChecker(foo) is fooChecker True >>> fooChecker.check(foo, 'a') >>> try: ... fooChecker.check(foo, 'b') # doctest: +ELLIPSIS ... except ForbiddenAttribute as e: ... e ForbiddenAttribute('b', ) and that a `Wrapper` object uses `wrappeChecker`: .. doctest:: >>> wrapper = Wrapper(foo) >>> selectChecker(wrapper) is wrapperChecker True >>> wrapperChecker.check(wrapper, 'b') >>> try: ... wrapperChecker.check(wrapper, 'a') # doctest: +ELLIPSIS ... except ForbiddenAttribute as e: ... e ForbiddenAttribute('a', ) (Note that the object description says `Foo` because the object is a proxy and generally looks and acts like the object it's proxying.) When we access wrapper's ``__Security_checker__`` attribute, we invoke the decorated security checker descriptor. The decorator's job is to make sure checkers from both objects are used when available. In this case, because both objects have checkers, we get a combined checker: .. doctest:: >>> from zope.security.checker import CombinedChecker >>> checker = wrapper.__Security_checker__ >>> type(checker) >>> checker.check(wrapper, 'a') >>> checker.check(wrapper, 'b') The decorator checker will work even with security proxied objects. To illustrate, we'll proxify `foo`: .. doctest:: >>> from zope.security.proxy import ProxyFactory >>> secure_foo = ProxyFactory(foo) >>> secure_foo.a 'a' >>> try: ... secure_foo.b # doctest: +ELLIPSIS ... except ForbiddenAttribute as e: ... e ForbiddenAttribute('b', ) when we wrap the secured `foo`: .. doctest:: >>> wrapper = Wrapper(secure_foo) we still get a combined checker: .. doctest:: >>> checker = wrapper.__Security_checker__ >>> type(checker) >>> checker.check(wrapper, 'a') >>> checker.check(wrapper, 'b') The decorator checker has three other scenarios: - the wrapper has a checker but the proxied object doesn't - the proxied object has a checker but the wrapper doesn't - neither the wrapper nor the proxied object have checkers When the wrapper has a checker but the proxied object doesn't: .. doctest:: >>> from zope.security.checker import NoProxy, _checkers >>> del _checkers[Foo] >>> defineChecker(Foo, NoProxy) >>> selectChecker(foo) is None True >>> selectChecker(wrapper) is wrapperChecker True the decorator uses only the wrapper checker: .. doctest:: >>> wrapper = Wrapper(foo) >>> wrapper.__Security_checker__ is wrapperChecker True When the proxied object has a checker but the wrapper doesn't: .. doctest:: >>> del _checkers[Wrapper] >>> defineChecker(Wrapper, NoProxy) >>> selectChecker(wrapper) is None True >>> del _checkers[Foo] >>> defineChecker(Foo, fooChecker) >>> selectChecker(foo) is fooChecker True the decorator uses only the proxied object checker: .. doctest:: >>> wrapper.__Security_checker__ is fooChecker True Finally, if neither the wrapper not the proxied have checkers: .. doctest:: >>> del _checkers[Foo] >>> defineChecker(Foo, NoProxy) >>> selectChecker(foo) is None True >>> selectChecker(wrapper) is None True the decorator doesn't have a checker: .. doctest:: >>> wrapper.__Security_checker__ Traceback (most recent call last): ... AttributeError: 'Foo' has no attribute '__Security_checker__' __Security_checker__ cannot be None, otherwise Checker.proxy blows up: >>> checker.proxy(wrapper) is wrapper True .. autoclass:: zope.security.decorator.SecurityCheckerDecoratorBase :members: :member-order: bysource .. autoclass:: zope.security.decorator.DecoratorBase :members: :member-order: bysource .. testcleanup:: from zope.component.testing import tearDown tearDown() zope.security-4.0.3/docs/api/simplepolicies.rst0000664000175000017500000000023612450532147022767 0ustar tseavertseaver00000000000000:mod:`zope.security.simplepolicies` =================================== .. automodule:: zope.security.simplepolicies :members: :member-order: bysource zope.security-4.0.3/docs/api/adapter.rst0000664000175000017500000000021112450532147021357 0ustar tseavertseaver00000000000000:mod:`zope.security.adapter` ============================ .. automodule:: zope.security.adapter :members: :member-order: bysource zope.security-4.0.3/docs/api/management.rst0000664000175000017500000000022212450532147022055 0ustar tseavertseaver00000000000000:mod:`zope.security.management` =============================== .. automodule:: zope.security.management :members: :member-order: bysource zope.security-4.0.3/docs/api/checker.rst0000664000175000017500000005474012450532147021363 0ustar tseavertseaver00000000000000:mod:`zope.security.checker` ============================ .. automodule:: zope.security.checker :members: :member-order: bysource Protections for Modules ----------------------- The :func:`zope.secuirty.checker.moduleChecker` API can be used to determine whether a module has been protected: Initially, there's no checker defined for the module: .. doctest:: >>> from zope.security.checker import moduleChecker >>> from zope.security.tests import test_zcml_functest >>> moduleChecker(test_zcml_functest) is None True We can add a checker using :func:`zope.security.metaconfigure.protectModule`: .. doctest:: >>> from zope.component import provideUtility >>> from zope.security.metaconfigure import protectModule >>> from zope.security.permission import Permission >>> from zope.security.interfaces import IPermission >>> TEST_PERM = 'zope.security.metaconfigure.test' >>> perm = Permission(TEST_PERM, '') >>> provideUtility(perm, IPermission, TEST_PERM) >>> protectModule(test_zcml_functest, 'foo', TEST_PERM) Now, the checker should exist and have an access dictionary with the name and permission: .. doctest:: >>> def pprint(ob, width=70): ... from pprint import PrettyPrinter ... PrettyPrinter(width=width).pprint(ob) >>> checker = moduleChecker(test_zcml_functest) >>> cdict = checker.get_permissions >>> pprint(cdict) {'foo': 'zope.security.metaconfigure.test'} If we define additional names, they will be added to the dict: >>> protectModule(test_zcml_functest, 'bar', TEST_PERM) >>> protectModule(test_zcml_functest, 'baz', TEST_PERM) >>> pprint(cdict) {'bar': 'zope.security.metaconfigure.test', 'baz': 'zope.security.metaconfigure.test', 'foo': 'zope.security.metaconfigure.test'} The allow directive creates actions for each named defined directly, or via interface: .. doctest:: >>> from zope.interface import Interface >>> from zope.interface import Attribute >>> from zope.security.metaconfigure import allow >>> class I1(Interface): ... def x(): pass ... y = Attribute("Y") >>> class I2(I1): ... def a(): pass ... b = Attribute("B") >>> class AContext(object): ... def __init__(self): ... self.actions = [] ... ... def action(self, discriminator, callable, args): ... self.actions.append( ... {'discriminator': discriminator, ... 'callable': int(callable is protectModule), ... 'args': args}) ... module='testmodule' >>> context = AContext() >>> allow(context, attributes=['foo', 'bar'], interface=[I1, I2]) >>> context.actions.sort(key=lambda a: a['discriminator']) >>> pprint(context.actions) [{'args': ('testmodule', 'a', 'zope.Public'), 'callable': 1, 'discriminator': ('http://namespaces.zope.org/zope:module', 'testmodule', 'a')}, {'args': ('testmodule', 'b', 'zope.Public'), 'callable': 1, 'discriminator': ('http://namespaces.zope.org/zope:module', 'testmodule', 'b')}, {'args': ('testmodule', 'bar', 'zope.Public'), 'callable': 1, 'discriminator': ('http://namespaces.zope.org/zope:module', 'testmodule', 'bar')}, {'args': ('testmodule', 'foo', 'zope.Public'), 'callable': 1, 'discriminator': ('http://namespaces.zope.org/zope:module', 'testmodule', 'foo')}, {'args': ('testmodule', 'x', 'zope.Public'), 'callable': 1, 'discriminator': ('http://namespaces.zope.org/zope:module', 'testmodule', 'x')}, {'args': ('testmodule', 'y', 'zope.Public'), 'callable': 1, 'discriminator': ('http://namespaces.zope.org/zope:module', 'testmodule', 'y')}] The provide directive creates actions for each named defined directly, or via interface: .. doctest:: >>> from zope.security.metaconfigure import require >>> class RContext(object): ... def __init__(self): ... self.actions = [] ... def action(self, discriminator, callable, args): ... self.actions.append( ... {'discriminator': discriminator, ... 'callable': int(callable is protectModule), ... 'args': args}) ... module='testmodule' >>> context = RContext() >>> require(context, attributes=['foo', 'bar'], ... interface=[I1, I2], permission='p') >>> context.actions.sort(key=lambda a: a['discriminator']) >>> pprint(context.actions) [{'args': ('testmodule', 'a', 'p'), 'callable': 1, 'discriminator': ('http://namespaces.zope.org/zope:module', 'testmodule', 'a')}, {'args': ('testmodule', 'b', 'p'), 'callable': 1, 'discriminator': ('http://namespaces.zope.org/zope:module', 'testmodule', 'b')}, {'args': ('testmodule', 'bar', 'p'), 'callable': 1, 'discriminator': ('http://namespaces.zope.org/zope:module', 'testmodule', 'bar')}, {'args': ('testmodule', 'foo', 'p'), 'callable': 1, 'discriminator': ('http://namespaces.zope.org/zope:module', 'testmodule', 'foo')}, {'args': ('testmodule', 'x', 'p'), 'callable': 1, 'discriminator': ('http://namespaces.zope.org/zope:module', 'testmodule', 'x')}, {'args': ('testmodule', 'y', 'p'), 'callable': 1, 'discriminator': ('http://namespaces.zope.org/zope:module', 'testmodule', 'y')}] Protections for standard objects -------------------------------- .. doctest:: >>> from zope.security.checker import ProxyFactory >>> from zope.security.interfaces import ForbiddenAttribute >>> def check_forbidden_get(object, attr): ... from zope.security.interfaces import ForbiddenAttribute ... try: ... return getattr(object, attr) ... except ForbiddenAttribute as e: ... return 'ForbiddenAttribute: %s' % e.args[0] >>> def check_forbidden_setitem(object, item, value): ... from zope.security.interfaces import ForbiddenAttribute ... try: ... object[item] = value ... except ForbiddenAttribute as e: ... return 'ForbiddenAttribute: %s' % e.args[0] >>> def check_forbidden_delitem(object, item): ... from zope.security.interfaces import ForbiddenAttribute ... try: ... del object[item] ... except ForbiddenAttribute as e: ... return 'ForbiddenAttribute: %s' % e.args[0] >>> def check_forbidden_call(callable, *args): # ** ... from zope.security.interfaces import ForbiddenAttribute ... try: ... return callable(*args) # ** ... except ForbiddenAttribute as e: ... return 'ForbiddenAttribute: %s' % e.args[0] Rocks ##### Rocks are immuatle, non-callable objects without interesting methods. They *don't* get proxied. .. doctest:: >>> int(type(ProxyFactory( object() )) is object) 1 >>> int(type(ProxyFactory( 1 )) is int) 1 >>> int(type(ProxyFactory( 1.0 )) is float) 1 >>> int(type(ProxyFactory( 1j )) is complex) 1 >>> int(type(ProxyFactory( None )) is type(None)) 1 >>> int(type(ProxyFactory( 'xxx' )) is str) 1 >>> int(type(ProxyFactory( True )) is type(True)) 1 Datetime-reltatd instances are rocks, too: .. doctest:: >>> from datetime import timedelta, datetime, date, time, tzinfo >>> int(type(ProxyFactory( timedelta(1) )) is timedelta) 1 >>> int(type(ProxyFactory( datetime(2000, 1, 1) )) is datetime) 1 >>> int(type(ProxyFactory( date(2000, 1, 1) )) is date) 1 >>> int(type(ProxyFactory( time() )) is time) 1 >>> int(type(ProxyFactory( tzinfo() )) is tzinfo) 1 >>> try: ... from pytz import UTC ... except ImportError: # pytz checker only if pytz is present. ... 1 ... else: ... int(type(ProxyFactory( UTC )) is type(UTC)) 1 dicts ##### We can do everything we expect to be able to do with proxied dicts. .. doctest:: >>> d = ProxyFactory({'a': 1, 'b': 2}) >>> check_forbidden_get(d, 'clear') # Verify that we are protected 'ForbiddenAttribute: clear' >>> check_forbidden_setitem(d, 3, 4) # Verify that we are protected 'ForbiddenAttribute: __setitem__' >>> d['a'] 1 >>> len(d) 2 >>> sorted(list(d)) ['a', 'b'] >>> d.get('a') 1 >>> int('a' in d) 1 >>> c = d.copy() >>> check_forbidden_get(c, 'clear') 'ForbiddenAttribute: clear' >>> int(str(c) in ("{'a': 1, 'b': 2}", "{'b': 2, 'a': 1}")) 1 >>> int(repr(c) in ("{'a': 1, 'b': 2}", "{'b': 2, 'a': 1}")) 1 >>> def sorted(x): ... x = list(x) ... x.sort() ... return x >>> sorted(d.keys()) ['a', 'b'] >>> sorted(d.values()) [1, 2] >>> sorted(d.items()) [('a', 1), ('b', 2)] Always available (note, that dicts in python-3.x are not orderable, so we are not checking that under python > 2): .. doctest:: >>> int(d != d) 0 >>> int(bool(d)) 1 >>> int(d.__class__ == dict) 1 lists ##### We can do everything we expect to be able to do with proxied lists. .. doctest:: >>> l = ProxyFactory([1, 2]) >>> check_forbidden_delitem(l, 0) 'ForbiddenAttribute: __delitem__' >>> check_forbidden_setitem(l, 0, 3) 'ForbiddenAttribute: __setitem__' >>> l[0] 1 >>> l[0:1] [1] >>> check_forbidden_setitem(l[:1], 0, 2) 'ForbiddenAttribute: __setitem__' >>> len(l) 2 >>> tuple(l) (1, 2) >>> int(1 in l) 1 >>> l.index(2) 1 >>> l.count(2) 1 >>> str(l) '[1, 2]' >>> repr(l) '[1, 2]' >>> l + l [1, 2, 1, 2] Always available: .. doctest:: >>> int(l < l) 0 >>> int(l > l) 0 >>> int(l <= l) 1 >>> int(l >= l) 1 >>> int(l == l) 1 >>> int(l != l) 0 >>> int(bool(l)) 1 >>> int(l.__class__ == list) 1 tuples ###### We can do everything we expect to be able to do with proxied tuples. .. doctest:: >>> from zope.security.checker import ProxyFactory >>> l = ProxyFactory((1, 2)) >>> l[0] 1 >>> l[0:1] (1,) >>> len(l) 2 >>> list(l) [1, 2] >>> int(1 in l) 1 >>> str(l) '(1, 2)' >>> repr(l) '(1, 2)' >>> l + l (1, 2, 1, 2) Always available: .. doctest:: >>> int(l < l) 0 >>> int(l > l) 0 >>> int(l <= l) 1 >>> int(l >= l) 1 >>> int(l == l) 1 >>> int(l != l) 0 >>> int(bool(l)) 1 >>> int(l.__class__ == tuple) 1 sets #### we can do everything we expect to be able to do with proxied sets. .. doctest:: >>> us = set((1, 2)) >>> s = ProxyFactory(us) >>> check_forbidden_get(s, 'add') # Verify that we are protected 'ForbiddenAttribute: add' >>> check_forbidden_get(s, 'remove') # Verify that we are protected 'ForbiddenAttribute: remove' >>> check_forbidden_get(s, 'discard') # Verify that we are protected 'ForbiddenAttribute: discard' >>> check_forbidden_get(s, 'pop') # Verify that we are protected 'ForbiddenAttribute: pop' >>> check_forbidden_get(s, 'clear') # Verify that we are protected 'ForbiddenAttribute: clear' >>> len(s) 2 >>> 1 in s True >>> 1 not in s False >>> s.issubset(set((1,2,3))) True >>> s.issuperset(set((1,2,3))) False >>> c = s.union(set((2, 3))) >>> sorted(c) [1, 2, 3] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = s | set((2, 3)) >>> sorted(c) [1, 2, 3] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = s | ProxyFactory(set((2, 3))) >>> sorted(c) [1, 2, 3] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = set((2, 3)) | s >>> sorted(c) [1, 2, 3] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = s.intersection(set((2, 3))) >>> sorted(c) [2] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = s & set((2, 3)) >>> sorted(c) [2] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = s & ProxyFactory(set((2, 3))) >>> sorted(c) [2] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = set((2, 3)) & s >>> sorted(c) [2] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = s.difference(set((2, 3))) >>> sorted(c) [1] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = s - ProxyFactory(set((2, 3))) >>> sorted(c) [1] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = s - set((2, 3)) >>> sorted(c) [1] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = set((2, 3)) - s >>> sorted(c) [3] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = s.symmetric_difference(set((2, 3))) >>> sorted(c) [1, 3] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = s ^ set((2, 3)) >>> sorted(c) [1, 3] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = s ^ ProxyFactory(set((2, 3))) >>> sorted(c) [1, 3] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = set((2, 3)) ^ s >>> sorted(c) [1, 3] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = s.copy() >>> sorted(c) [1, 2] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> str(s) == str(us) True >>> repr(s) == repr(us) True Always available: >>> s < us False >>> s > us False >>> s <= us True >>> s >= us True >>> s == us True >>> s != us False Note that you can't compare proxied sets with other proxied sets due a limitaion in the set comparison functions which won't work with any kind of proxy. .. doctest:: >>> bool(s) True >>> s.__class__ == set True frozensets ########## we can do everything we expect to be able to do with proxied frozensets. .. doctest:: >>> def check_forbidden_get(object, attr): ... from zope.security.interfaces import ForbiddenAttribute ... try: ... return getattr(object, attr) ... except ForbiddenAttribute as e: ... return 'ForbiddenAttribute: %s' % e.args[0] >>> from zope.security.checker import ProxyFactory >>> from zope.security.interfaces import ForbiddenAttribute >>> us = frozenset((1, 2)) >>> s = ProxyFactory(us) >>> check_forbidden_get(s, 'add') # Verify that we are protected 'ForbiddenAttribute: add' >>> check_forbidden_get(s, 'remove') # Verify that we are protected 'ForbiddenAttribute: remove' >>> check_forbidden_get(s, 'discard') # Verify that we are protected 'ForbiddenAttribute: discard' >>> check_forbidden_get(s, 'pop') # Verify that we are protected 'ForbiddenAttribute: pop' >>> check_forbidden_get(s, 'clear') # Verify that we are protected 'ForbiddenAttribute: clear' >>> len(s) 2 >>> 1 in s True >>> 1 not in s False >>> s.issubset(frozenset((1,2,3))) True >>> s.issuperset(frozenset((1,2,3))) False >>> c = s.union(frozenset((2, 3))) >>> sorted(c) [1, 2, 3] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = s | frozenset((2, 3)) >>> sorted(c) [1, 2, 3] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = s | ProxyFactory(frozenset((2, 3))) >>> sorted(c) [1, 2, 3] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = frozenset((2, 3)) | s >>> sorted(c) [1, 2, 3] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = s.intersection(frozenset((2, 3))) >>> sorted(c) [2] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = s & frozenset((2, 3)) >>> sorted(c) [2] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = s & ProxyFactory(frozenset((2, 3))) >>> sorted(c) [2] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = frozenset((2, 3)) & s >>> sorted(c) [2] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = s.difference(frozenset((2, 3))) >>> sorted(c) [1] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = s - ProxyFactory(frozenset((2, 3))) >>> sorted(c) [1] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = s - frozenset((2, 3)) >>> sorted(c) [1] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = frozenset((2, 3)) - s >>> sorted(c) [3] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = s.symmetric_difference(frozenset((2, 3))) >>> sorted(c) [1, 3] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = s ^ frozenset((2, 3)) >>> sorted(c) [1, 3] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = s ^ ProxyFactory(frozenset((2, 3))) >>> sorted(c) [1, 3] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = frozenset((2, 3)) ^ s >>> sorted(c) [1, 3] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> c = s.copy() >>> sorted(c) [1, 2] >>> check_forbidden_get(c, 'add') 'ForbiddenAttribute: add' >>> str(s) == str(us) True >>> repr(s) == repr(us) True Always available: >>> s < us False >>> s > us False >>> s <= us True >>> s >= us True >>> s == us True >>> s != us False Note that you can't compare proxied sets with other proxied sets due a limitaion in the frozenset comparison functions which won't work with any kind of proxy. .. doctest:: >>> bool(s) True >>> s.__class__ == frozenset True iterators ######### .. doctest:: >>> [a for a in ProxyFactory(iter([1, 2]))] [1, 2] >>> list(ProxyFactory(iter([1, 2]))) [1, 2] >>> list(ProxyFactory(iter((1, 2)))) [1, 2] >>> list(ProxyFactory(iter({1:1, 2:2}))) [1, 2] >>> def f(): ... for i in 1, 2: ... yield i ... >>> list(ProxyFactory(f())) [1, 2] >>> list(ProxyFactory(f)()) [1, 2] We can iterate over custom sequences, too: .. doctest:: >>> class X(object): ... d = 1, 2, 3 ... def __getitem__(self, i): ... return self.d[i] ... >>> x = X() We can iterate over sequences .. doctest:: >>> list(x) [1, 2, 3] >>> from zope.security.checker import NamesChecker >>> from zope.security.checker import ProxyFactory >>> c = NamesChecker(['__getitem__', '__len__']) >>> p = ProxyFactory(x, c) Even if they are proxied .. doctest:: >>> list(p) [1, 2, 3] But if the class has an iter: .. doctest:: >>> X.__iter__ = lambda self: iter(self.d) >>> list(x) [1, 2, 3] We shouldn't be able to iterate if we don't have an assertion: .. doctest:: >>> check_forbidden_call(list, p) 'ForbiddenAttribute: __iter__' New-style classes ################# .. doctest:: >>> from zope.security.checker import NamesChecker >>> class C(object): ... x = 1 ... y = 2 >>> C = ProxyFactory(C) >>> check_forbidden_call(C) 'ForbiddenAttribute: __call__' >>> check_forbidden_get(C, '__dict__') 'ForbiddenAttribute: __dict__' >>> s = str(C) >>> s = repr(C) >>> int(C.__module__ == __name__) 1 >>> len(C.__bases__) 1 >>> len(C.__mro__) 2 Always available: .. doctest:: >>> int(C == C) 1 >>> int(C != C) 0 >>> int(bool(C)) 1 >>> int(C.__class__ == type) 1 New-style Instances ################### .. doctest:: >>> class C(object): ... x = 1 ... y = 2 >>> c = ProxyFactory(C(), NamesChecker(['x'])) >>> check_forbidden_get(c, 'y') 'ForbiddenAttribute: y' >>> check_forbidden_get(c, 'z') 'ForbiddenAttribute: z' >>> c.x 1 >>> int(c.__class__ == C) 1 Always available: .. doctest:: >>> int(c == c) 1 >>> int(c != c) 0 >>> int(bool(c)) 1 >>> int(c.__class__ == C) 1 Classic Classes ############### .. doctest:: >>> class C: ... x = 1 >>> C = ProxyFactory(C) >>> check_forbidden_call(C) 'ForbiddenAttribute: __call__' >>> check_forbidden_get(C, '__dict__') 'ForbiddenAttribute: __dict__' >>> s = str(C) >>> s = repr(C) >>> int(C.__module__ == __name__) 1 >>> len(C.__bases__) 1 Always available: .. doctest:: >>> int(C == C) 1 >>> int(C != C) 0 >>> int(bool(C)) 1 Classic Instances ################# .. doctest:: >>> class C(object): ... x, y = 1, 2 >>> c = ProxyFactory(C(), NamesChecker(['x'])) >>> check_forbidden_get(c, 'y') 'ForbiddenAttribute: y' >>> check_forbidden_get(c, 'z') 'ForbiddenAttribute: z' >>> c.x 1 >>> int(c.__class__ == C) 1 Always available: .. doctest:: >>> int(c == c) 1 >>> int(c != c) 0 >>> int(bool(c)) 1 >>> int(c.__class__ == C) 1 Interfaces and declarations ########################### We can still use interfaces though proxies: .. doctest:: >>> from zope.interface import directlyProvides >>> from zope.interface import implementer >>> from zope.interface import provider >>> class I(Interface): ... pass >>> class IN(Interface): ... pass >>> class II(Interface): ... pass >>> @implementer(I) ... @provider(IN) ... class N(object): ... pass >>> n = N() >>> directlyProvides(n, II) >>> N = ProxyFactory(N) >>> n = ProxyFactory(n) >>> I.implementedBy(N) True >>> IN.providedBy(N) True >>> I.providedBy(n) True >>> II.providedBy(n) True abstract Base Classes ##################### We work with the ABCMeta meta class: .. doctest:: >>> import abc >>> class MyABC: ... __metaclass__ = abc.ABCMeta >>> class Foo(MyABC): pass >>> class Bar(Foo): pass >>> PBar = ProxyFactory(Bar) >>> [c.__name__ for c in PBar.__mro__] ['Bar', 'Foo', 'MyABC', 'object'] >>> check_forbidden_call(PBar) 'ForbiddenAttribute: __call__' >>> check_forbidden_get(PBar, '__dict__') 'ForbiddenAttribute: __dict__' >>> s = str(PBar) >>> s = repr(PBar) >>> int(PBar.__module__ == __name__) 1 >>> len(PBar.__bases__) 1 Always available: .. doctest:: >>> int(PBar == PBar) 1 >>> int(PBar != PBar) 0 >>> int(bool(PBar)) 1 >>> int(PBar.__class__ == type) 1 zope.security-4.0.3/docs/api/protectclass.rst0000664000175000017500000000023012450532147022446 0ustar tseavertseaver00000000000000:mod:`zope.security.protectclass` ================================= .. automodule:: zope.security.protectclass :members: :member-order: bysource zope.security-4.0.3/docs/api/proxy.rst0000664000175000017500000000140012450532147021121 0ustar tseavertseaver00000000000000:mod:`zope.security.proxy` =============================== .. testsetup:: from zope.component.testing import setUp setUp() .. autofunction:: zope.security.proxy.getTestProxyItems .. autofunction:: zope.security.proxy.isinstance .. doctest:: >>> from zope.security.proxy import isinstance >>> class C1(object): ... pass >>> c = C1() >>> isinstance(c, C1) True >>> from zope.security.checker import ProxyFactory >>> isinstance(ProxyFactory(c), C1) True >>> class C2(C1): ... pass >>> c = C2() >>> isinstance(c, C1) True >>> from zope.security.checker import ProxyFactory >>> isinstance(ProxyFactory(c), C1) True .. testcleanup:: from zope.component.testing import tearDown tearDown() zope.security-4.0.3/docs/api/zcml.rst0000664000175000017500000000441712450532147020720 0ustar tseavertseaver00000000000000:mod:`zope.security.zcml` =============================== Configuring security via ZCML ----------------------------- :mod:`zope.security` provides a ZCML file that configures some utilities and a couple of permissions: .. doctest:: >>> from zope.component import getGlobalSiteManager >>> from zope.configuration.xmlconfig import XMLConfig >>> from zope.component.testing import setUp >>> import zope.security >>> setUp() # clear global component registry >>> XMLConfig('permissions.zcml', zope.security)() >>> len(list(getGlobalSiteManager().registeredUtilities())) 7 Clear the current state: .. doctest:: >>> from zope.component.testing import setUp, tearDown >>> tearDown() >>> setUp() >>> XMLConfig('configure.zcml', zope.security)() >>> len(list(getGlobalSiteManager().registeredUtilities())) 10 .. autoclass:: zope.security.zcml.Permission :members: :member-order: bysource Let's look at an example: .. doctest:: >>> from zope.security.zcml import Permission >>> class FauxContext(object): ... permission_mapping = {'zope.ManageCode':'zope.private'} ... _actions = [] ... def action(self, **kws): ... self._actions.append(kws) >>> context = FauxContext() >>> field = Permission().bind(context) Let's test the fromUnicode method: .. doctest:: >>> field.fromUnicode(u'zope.foo') 'zope.foo' >>> field.fromUnicode(u'zope.ManageCode') 'zope.private' Now let's see whether validation works alright .. doctest:: >>> field._validate('zope.ManageCode') >>> context._actions[0]['args'] (None, 'zope.foo') >>> from zope.schema.interfaces import InvalidId >>> try: ... field._validate('3 foo') ... except InvalidId as e: ... e InvalidId('3 foo') zope.Public is always valid >>> field._validate('zope.Public') .. autointerface:: zope.security.zcml.ISecurityPolicyDirective :members: :member-order: bysource .. autofunction:: zope.security.zcml.securityPolicy .. autointerface:: zope.security.zcml.IPermissionDirective :members: :member-order: bysource .. autofunction:: zope.security.zcml.permission .. autointerface:: zope.security.zcml.IRedefinePermission :members: :member-order: bysource .. autofunction:: zope.security.zcml.redefinePermission zope.security-4.0.3/docs/api/permission.rst0000664000175000017500000000617712450532147022150 0ustar tseavertseaver00000000000000:mod:`zope.security.permission` =============================== .. testsetup:: from zope.component.testing import setUp setUp() .. autoclass:: zope.security.permission.Permission :members: :member-order: bysource .. autofunction:: zope.security.permission.checkPermission .. doctest:: >>> from zope.security.permission import checkPermission >>> from zope.component import provideUtility >>> from zope.security.interfaces import IPermission >>> from zope.security.permission import Permission >>> x = Permission('x') >>> provideUtility(x, IPermission, 'x') >>> checkPermission(None, 'x') >>> checkPermission(None, 'y') Traceback (most recent call last): ... ValueError: ('Undefined permission id', 'y') The :data:`zope.security.checker.CheckerPublic` permission always exists: .. doctest:: >>> from zope.security.checker import CheckerPublic >>> checkPermission(None, CheckerPublic) .. autofunction:: zope.security.permission.allPermissions .. doctest:: >>> from zope.security.permission import allPermissions >>> from zope.component import provideUtility >>> y = Permission('y') >>> provideUtility(y, IPermission, 'y') >>> ids = list(allPermissions(None)) >>> ids.sort() >>> ids ['x', 'y'] .. autofunction:: zope.security.permission.PermissionsVocabulary To illustrate, we need to register the permissions vocabulary: .. doctest:: >>> from zope.security.permission import PermissionsVocabulary >>> from zope.schema.vocabulary import _clear >>> _clear() >>> from zope.schema.vocabulary import getVocabularyRegistry >>> registry = getVocabularyRegistry() >>> registry.register('Permissions', PermissionsVocabulary) We can now lookup the permissions we created earlier using the vocabulary: .. doctest:: >>> vocab = registry.get(None, 'Permissions') >>> vocab.getTermByToken('x').value is x True >>> vocab.getTermByToken('y').value is y True .. autofunction:: zope.security.permission.PermissionIdsVocabulary To illustrate, we need to register the permission IDs vocabulary: .. doctest:: >>> from zope.security.permission import PermissionIdsVocabulary >>> registry.register('Permission Ids', PermissionIdsVocabulary) We also need to register the special 'zope.Public' permission: >>> provideUtility(Permission('zope.Public'), IPermission, 'zope.Public') We can now lookup these permissions using the vocabulary: .. doctest:: >>> vocab = registry.get(None, 'Permission Ids') The non-public permissions 'x' and 'y' are string values: .. doctest:: >>> vocab.getTermByToken('x').value 'x' >>> vocab.getTermByToken('y').value 'y' However, the public permission value is CheckerPublic: .. doctest:: >>> vocab.getTermByToken('zope.Public').value is CheckerPublic True and its title is shortened: .. doctest:: >>> vocab.getTermByToken('zope.Public').title 'Public' The terms are sorted by title except for the public permission, which is listed first: .. doctest:: >>> [term.title for term in vocab] ['Public', 'x', 'y'] .. testcleanup:: from zope.component.testing import tearDown tearDown() zope.security-4.0.3/docs/api/testing.rst0000664000175000017500000000021112450532147021414 0ustar tseavertseaver00000000000000:mod:`zope.security.testing` ============================ .. automodule:: zope.security.testing :members: :member-order: bysource zope.security-4.0.3/docs/api/interfaces.rst0000664000175000017500000000364512450532147022100 0ustar tseavertseaver00000000000000:mod:`zope.security.interfaces` =============================== .. automodule:: zope.security.interfaces Exceptions ########## .. autointerface:: IUnauthorized :members: :member-order: bysource .. autoexception:: Unauthorized .. autointerface:: IForbidden :members: :member-order: bysource .. autoexception:: Forbidden .. autointerface:: IForbiddenAttribute :members: :member-order: bysource .. autoexception:: ForbiddenAttribute Utilities ########## .. autointerface:: ISecurityManagement :members: :member-order: bysource .. autointerface:: ISecurityChecking :members: :member-order: bysource .. autointerface:: ISecurityProxyFactory :members: :member-order: bysource .. autointerface:: IChecker :members: :member-order: bysource .. autointerface:: INameBasedChecker :members: :member-order: bysource .. autointerface:: ISecurityPolicy :members: :member-order: bysource Principals ########## .. autointerface:: IInteraction :members: :member-order: bysource .. autointerface:: IParticipation :members: :member-order: bysource .. autoexception:: NoInteraction .. autointerface:: IInteractionManagement :members: :member-order: bysource .. autointerface:: IPrincipal :members: :member-order: bysource .. autointerface:: IGroupAwarePrincipal :members: :member-order: bysource .. autointerface:: IGroupClosureAwarePrincipal :members: :member-order: bysource .. autointerface:: IGroup :members: :member-order: bysource .. autointerface:: IMemberGetterGroup :members: :member-order: bysource .. autointerface:: IMemberAwareGroup :members: :member-order: bysource .. autointerface:: IPermission :members: :member-order: bysource zope.security-4.0.3/docs/conf.py0000664000175000017500000002004712450532147017744 0ustar tseavertseaver00000000000000# -*- coding: utf-8 -*- # # zope.security documentation build configuration file, created by # sphinx-quickstart on Sun Dec 23 12:19:39 2012. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.insert(0, os.path.abspath('.')) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.viewcode', 'repoze.sphinx.autointerface', ] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'zope.security' copyright = u'2012, Zope Foundation Contributors ' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = '4.0' # The full version, including alpha/beta/rc tags. release = '4.0dev' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'default' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'zopesecuritydoc' # -- Options for LaTeX output -------------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). #'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). #'pointsize': '10pt', # Additional stuff for the LaTeX preamble. #'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'zopesecurity.tex', u'zope.security Documentation', u'Zope Foundation Contributors \\textless{}zope-dev@zope.org\\textgreater{}', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'zopesecurity', u'zope.security Documentation', [u'Zope Foundation Contributors '], 1) ] # If true, show URL addresses after external links. #man_show_urls = False # -- Options for Texinfo output ------------------------------------------------ # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ('index', 'zopesecurity', u'zope.security Documentation', u'Zope Foundation Contributors ', 'zopesecurity', 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. #texinfo_appendices = [] # If false, no module index is generated. #texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. #texinfo_show_urls = 'footnote' # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = {'http://docs.python.org/': None} zope.security-4.0.3/docs/index.rst0000664000175000017500000000077212460764536020323 0ustar tseavertseaver00000000000000:mod:`zope.security` Documentation ================================== Narrative Documentation ----------------------- .. toctree:: :maxdepth: 2 narr hacking API Reference ------------- .. toctree:: :maxdepth: 2 api/interfaces api/adapter api/checker api/decorator api/management api/permission api/protectclass api/proxy api/simplepolicies api/testing api/zcml Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` zope.security-4.0.3/docs/narr.rst0000664000175000017500000004745512450532147020155 0ustar tseavertseaver00000000000000Overview ======== Introduction ------------ The Security framework provides a generic mechanism to implement security policies on Python objects. This introduction provides a tutorial of the framework explaining concepts, design, and going through sample usage from the perspective of a Python programmer using the framework outside of Zope. Definitions ----------- Principal ~~~~~~~~~ A generalization of a concept of a user. Permission ~~~~~~~~~~ A kind of access, i.e. permission to READ vs. permission to WRITE. Fundamentally the whole security framework is organized around checking permissions on objects. Purpose ------- The security framework's primary purpose is to guard and check access to Python objects. It does this by providing mechanisms for explicit and implicit security checks on attribute access for objects. Attribute names are mapped onto permission names when checking access and the implementation of the security check is defined by the security policy, which receives the object, the permission name, and an interaction. Interactions are objects that represent the use of the system by one or more principals. An interaction contains a list of participations, which represents the way a single principal participates in the interaction. An HTTP request is one example of a participation. Its important to keep in mind that the policy provided is just a default, and it can be substituted with one which doesn't care about principals or interactions at all. Framework Components -------------------- Low Level Components ~~~~~~~~~~~~~~~~~~~~ These components provide the infrastructure for guarding attribute access and providing hooks into the higher level security framework. Checkers ~~~~~~~~ A checker is associated with an object kind, and provides the hooks that map attribute checks onto permissions deferring to the security manager (which in turn defers to the policy) to perform the check. Additionally, checkers provide for creating proxies of objects associated with the checker. There are several implementation variants of checkers, such as checkers that grant access based on attribute names. Proxies ~~~~~~~ Wrappers around Python objects that implicitly guard access to their wrapped contents by delegating to their associated checker. Proxies are also viral in nature, in that values returned by proxies are also proxied. High Level Components --------------------- Security Management ~~~~~~~~~~~~~~~~~~~ Provides accessors for setting up interactions and the global security policy. Interaction ~~~~~~~~~~~ Stores transient information on the list of participations. Participation ~~~~~~~~~~~~~ Stores information about a principal participating in the interaction. Security Policy ~~~~~~~~~~~~~~~ Provides a single method that accepts the object, the permission, and the interaction of the access being checked and is used to implement the application logic for the security framework. Narrative (agent sandbox) ------------------------- As an example we take a look at constructing a multi-agent distributed system, and then adding a security layer using the Zope security model onto it. Scenario ~~~~~~~~ Our agent simulation consists of autonomous agents that live in various agent homes/sandboxes and perform actions that access services available at their current home. Agents carry around authentication tokens which signify their level of access within any given home. Additionally agents attempt to migrate from home to home randomly. The agent simulation was constructed separately from any security aspects. Now we want to define and integrate a security model into the simulation. The full code for the simulation and the security model is available separately; we present only relevant code snippets here for illustration as we go through the implementation process. For the agent simulation we want to add a security model such that we group agents into two authentication groups, "norse legends", including the principals thor, odin, and loki, and "greek men", including prometheus, archimedes, and thucydides. We associate permissions with access to services and homes. We differentiate the homes such that certain authentication groups only have access to services or the home itself based on the local settings of the home in which they reside. We define the homes/sandboxes - origin - all agents start here, and have access to all services here. - valhalla - only agents in the authentication group 'norse legend' can reside here. - jail - all agents can come here, but only 'norse legend's can leave or access services. Process ~~~~~~~ Loosely we define a process for implementing this security model - mapping permissions onto actions - mapping authentication tokens onto permissions - implementing checkers and security policies that use our authentication tokens and permissions. - binding checkers to our simulation classes - inserting the hooks into the original simulation code to add proxy wrappers to automatically check security. - inserting hooks into the original simulation to register the agents as the active principal in an interaction. Defining a Permission Model ~~~~~~~~~~~~~~~~~~~~~~~~~~~ We define the following permissions:: NotAllowed = 'Not Allowed' Public = Checker.CheckerPublic TransportAgent = 'Transport Agent' AccessServices = 'Access Services' AccessAgents = 'Access Agents' AccessTimeService = 'Access Time Services' AccessAgentService = 'Access Agent Service' AccessHomeService = 'Access Home Service' and create a dictionary database mapping homes to authentication groups which are linked to associated permissions. Defining and Binding Checkers ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Checkers are the foundational unit for the security framework. They define what attributes can be accessed or set on a given instance. They can be used implicitly via Proxy objects, to guard all attribute access automatically or explicitly to check a given access for an operation. Checker construction expects two functions or dictionaries, one is used to map attribute names to permissions for attribute access and another to do the same for setting attributes. We use the following checker factory function:: def PermissionMapChecker(permissions_map={}, setattr_permission_func=NoSetAttr): res = {} for k,v in permissions_map.items(): for iv in v: res[iv]=k return checker.Checker(res.get, setattr_permission_func) time_service_checker = PermissionMapChecker( # permission : [methods] {'AccessTimeService':['getTime']} ) with the NoSetAttr function defined as a lambda which always return the permission `NotAllowed`. To bind the checkers to the simulation classes we register our checkers with the security model's global checker registry:: import sandbox_simulation from zope.security.checker import defineChecker defineChecker(sandbox_simulation.TimeService, time_service_checker) Defining a Security Policy ~~~~~~~~~~~~~~~~~~~~~~~~~~ We implement our security policy such that it checks the current agent's authentication token against the given permission in the home of the object being accessed:: @implementer(ISecurityPolicy) class SimulationSecurityPolicy: createInteraction = staticmethod(simpleinteraction.createInteraction) def checkPermission(self, permission, object, interaction): home = object.getHome() db = getattr(SimulationSecurityDatabase, home.getId(), None) if db is None: return False allowed = db.get('any', ()) if permission in allowed or ALL in allowed: return True if interaction is None: return False if not interaction.participations: return False for participation in interaction.participations: token = participation.principal.getAuthenticationToken() allowed = db.get(token, ()) if permission not in allowed: return False return True There are no specific requirements for the interaction class, so we can just use `zope.security.simpleinteraction.Interaction`. Since an interaction can have more than one principal, we check that *all* of them are given the necessary permission. This is not really necessary since we only create interactions with a single active principal. There is some additional code present to allow for shortcuts in defining the permission database when defining permissions for all auth groups and all permissions. Integration ~~~~~~~~~~~ At this point we have implemented our security model, and we need to integrate it with our simulation model. We do so in three separate steps. First we make it such that agents only access homes that are wrapped in a security proxy. By doing this all access to homes and services (proxies have proxied return values for their methods) is implicitly guarded by our security policy. The second step is that we want to associate the active agent with the security context so the security policy will know which agent's authentication token to validate against. The third step is to set our security policy as the default policy for the Zope security framework. It is possible to create custom security policies at a finer grained than global, but such is left as an exercise for the reader. Interaction Access ~~~~~~~~~~~~~~~~~~ The *default* implementation of the interaction management interfaces defines interactions on a per thread basis with a function for an accessor. This model is not appropriate for all systems, as it restricts one to a single active interaction per thread at any given moment. Reimplementing the interaction access methods though is easily doable and is noted here for completeness. Perspectives ~~~~~~~~~~~~ It's important to keep in mind that there is a lot more that is possible using the security framework than what's been presented here. All of the interactions are interface based, such that if you need to re-implement the semantics to suite your application a new implementation of the interface will be sufficient. Additional possibilities range from restricted interpreters and dynamic loading of untrusted code to non Zope web application security systems. Insert imagination here ;-). Zope Perspective ~~~~~~~~~~~~~~~~ A Zope3 programmer will never commonly need to interact with the low level security framework. Zope3 defines a second security package over top the low level framework and authentication sources and checkers are handled via zcml registration. Still those developing Zope3 will hopefully find this useful as an introduction into the underpinnings of the security framework. Code ~~~~ The complete code for this example is available. - sandbox.py - the agent framework - sandbox_security.py - the security implementation and binding to the agent framework. Authors ~~~~~~~ - Kapil Thangavelu - Guido Wesdorp - Marius Gedminas Untrusted interpreters ====================== Untrusted programs are executed by untrusted interpreters. Untrusted interpreters make use of security proxies to prevent un-mediated access to assets. An untrusted interpreter defines an environment for running untrusted programs. All objects within the environment are either: - "safe" objects created internally by the environment or created in the course of executing the untrusted program, or - "basic" objects - security-proxied non-basic objects The environment includes proxied functions for accessing objects outside of the environment. These proxied functions provide the only way to access information outside the environment. Because these functions are proxied, as described below, any access to objects outside the environment is mediated by the target security functions. Safe objects are objects whose operations, except for attribute retrieval, and methods access only information stored within the objects or passed as arguments. Safe objects contained within the interpreter environment can contain only information that is already in the environment or computed directly from information that is included in the environment. For this reason, safe objects created within the environment cannot be used to directly access information outside the environment. Safe objects have some attributes that could (very) indirectly be used to access assets. For this reason, an untrusted interpreter always proxies the results of attribute accesses on a safe objects. Basic objects are safe objects that are used to represent elemental data values such as strings and numbers. Basic objects require a lower level of protection than non-basic objects, as will be described detail in a later section. Security proxies mediate all object operations. Any operation access is checked to see whether a subject is authorized to perform the operation. All operation results other than basic objects are, in turn, security proxied. Security proxies will be described in greater detail in a later section. Any operation on a security proxy that results in a non-basic object is also security proxied. All external resources needed to perform an operation are security proxied. Let's consider the trusted interpreter for evaluating URLs. In operation 1 of the example, the interpreter uses a proxied method for getting the system root object. Because the method is proxied, the result of calling the method and the operation is also proxied. The interpreter has a function for traversing objects. This function is proxied. When traversing an object, the function is passed an object and a name. In operation 2, the function is passed the result of operation 1, which is the proxied root object and the name 'A'. We may traverse an object by invoking an operation on it. For example, we may use an operation to get a sub-object. Because any operation on a proxied object returns a proxied object or a basic object, the result is either a proxied object or a basic object. Traversal may also look up a component. For example, in operation 1, we might look up a presentation component named "A" for the root object. In this case, the external object is not proxied, but, when it is returned from the traversal function, it is proxied (unless it is a a basic object) because the traversal function is proxied, and the result of calling a proxied function is proxied (unless the result is a basic object). Operation 3 proceeds in the same way. When we get to operation 4, we use a function for computing the default presentation of the result of operation 3. As with traversal, the result of getting the default presentation is either a proxied object or a basic object because the function for getting the default presentation is proxied. When we get to the last operation, we have either a proxied object or a basic object. If the result of operation 4 is a basic object, we simply convert it to a string and return it as the result page. If the result of operation 4 is a non-basic object, we invoke a render operation on it and return the result as a string. Note that an untrusted interpreter may or may not provide protection against excessive resource usage. Different interpreters will provide different levels of service with respect to limitations on resource usage. If an untrusted interpreter performs an attribute access, the trusted interpreter must proxy the result unless the result is a basic object. In summary, an untrusted interpreter assures that any access to assets is mediated through security proxies by creating an environment to run untrusted code and making sure that: - The only way to access anything from outside of the environment is to call functions that are proxied in the environment. - Results of any attribute access in the environment are proxied unless the results are basic objects. Security proxies ---------------- Security proxies are objects that wrap and mediate access to objects. The Python programming language used by Zope defines a set of specific named low-level operations. In addition to operations, Python objects can have attributes, used to represent data and methods. Attributes are accessed using a dot notation. Applications can, and usually do, define methods to provide extended object behaviors. Methods are accessed as attributes through the low-level operation named "__getattribute__". The Python code:: a.b() invokes 2 operations: 1. Use the low-level `__getattribute__` operation with the name "b". 2. Use the low-level '__call__' operation on the result of the first operation. For all operations except the `__getattribute__` and `__setattribute__` operations, security proxies have a permission value defined by the permission-declaration subsystem. Two special permission values indicate that access is either forbidden (never allowed) or public (always allowed). For all other permission values, the authorization subsystem is used to decide whether the subject has the permission for the proxied object. If the subject has the permission, then access to the operation is allowed. Otherwise, access is denied. For getting or setting attributes, a proxy has permissions for getting and a permission for setting attribute values for a given attribute name. As described above, these permissions may be one of the two special permission values indicating forbidden or public access, or another permission value that must be checked with the authorization system. For all objects, Zope defines the following operations to be always public: comparison "__lt__", "__le__", "__eq__", "__gt__", "__ge__", "__ne__" hash "__hash__" boolean value "__nonzero__" class introspection "__class__" interface introspection "__providedBy__", "__implements__" adaptation "__conform__" low-level string representation "__repr__" The result of an operation on a proxied object is a security proxy unless the result is a basic value. Basic objects ------------- Basic objects are safe immutable objects that contain only immutable subobjects. Examples of basic objects include: - Strings, - Integers (long and normal), - Floating-point objects, - Date-time objects, - Boolean objects (True and False), and - The special (nil) object, None. Basic objects are safe, so, as described earlier, operations on basic objects, other than attribute access, use only information contained within the objects or information passed to them. For this reason, basic objects cannot be used to access information outside of the untrusted interpreter environment. The decision not to proxy basic objects is largely an optimization. It allows low-level safe computation to be performed without unnecessary overhead, Note that a basic object could contain sensitive information, but such a basic object would need to be obtained by making a call on a proxied object. Therefore, the access to the basic object in the first place is mediated by the security functions. Rationale for mutable safe objects ---------------------------------- Some safe objects are not basic. For these objects, we proxy the objects if they originate from outside of the environment. We do this for two reasons: 1. Non-basic objects from outside the environment need to be proxied to prevent unauthorized access to information. 2. We need to prevent un-mediated change of information from outside of the environment. We don't proxy safe objects created within the environment. This is safe to do because such safe objects can contain and provide access to information already in the environment. Sometimes the interpreter or the interpreted program needs to be able to create simple data containers to hold information computed in the course of the program execution. Several safe container types are provided for this purpose. zope.security-4.0.3/docs/hacking.rst0000664000175000017500000003174012460764516020615 0ustar tseavertseaver00000000000000Hacking on :mod:`zope.security` =============================== Getting the Code ################ The main repository for :mod:`zope.security` is in the Zope Foundation Github repository: https://github.com/zopefoundation/zope.security You can get a read-only checkout from there: .. code-block:: sh $ git clone https://github.com/zopefoundation/zope.security.git or fork it and get a writeable checkout of your fork: .. code-block:: sh $ git clone git@github.com/jrandom/zope.security.git The project also mirrors the trunk from the Github repository as a Bazaar branch on Launchpad: https://code.launchpad.net/zope.security You can branch the trunk from there using Bazaar: .. code-block:: sh $ bzr branch lp:zope.security Working in a ``virtualenv`` ########################### Installing ---------- If you use the ``virtualenv`` package to create lightweight Python development environments, you can run the tests using nothing more than the ``python`` binary in a virtualenv. First, create a scratch environment: .. code-block:: sh $ /path/to/virtualenv --no-site-packages /tmp/hack-zope.security Next, get this package registered as a "development egg" in the environment: .. code-block:: sh $ /tmp/hack-zope.security/bin/python setup.py develop Running the tests ----------------- Then, you canrun the tests using the build-in ``setuptools`` testrunner: .. code-block:: sh $ /tmp/hack-zope.security/bin/python setup.py test ................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... ---------------------------------------------------------------------- Ran 643 tests in 0.000s OK If you have the :mod:`nose` package installed in the virtualenv, you can use its testrunner too: .. code-block:: sh $ /tmp/hack-zope.security/bin/easy_install nose ... $ /tmp/hack-zope.security/bin/nosetests ............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... ---------------------------------------------------------------------- Ran 655 tests in 0.000s OK If you have the :mod:`coverage` pacakge installed in the virtualenv, you can see how well the tests cover the code: .. code-block:: sh $ /tmp/hack-zope.security/bin/easy_install nose coverage ... $ /tmp/hack-zope.security/bin/nosetests --with coverage ............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... Name Stmts Miss Cover Missing --------------------------------------------------------------- zope/security.py 4 0 100% zope/security/_compat.py 9 0 100% zope/security/_definitions.py 11 0 100% zope/security/adapter.py 45 0 100% zope/security/checker.py 333 0 100% zope/security/decorator.py 33 0 100% zope/security/i18n.py 4 0 100% zope/security/interfaces.py 65 0 100% zope/security/management.py 62 0 100% zope/security/metaconfigure.py 108 0 100% zope/security/metadirectives.py 38 0 100% zope/security/permission.py 46 0 100% zope/security/protectclass.py 39 0 100% zope/security/proxy.py 164 19 88% 55, 86, 97, 119-121, 127-129, 143-144, 153-154, 158-159, 163-164, 298, 330 zope/security/simplepolicies.py 32 0 100% zope/security/zcml.py 43 0 100% --------------------------------------------------------------- TOTAL 1036 19 98% ---------------------------------------------------------------------- Ran 655 tests in 0.000s OK Building the documentation -------------------------- :mod:`zope.security` uses the nifty :mod:`Sphinx` documentation system for building its docs. Using the same virtualenv you set up to run the tests, you can build the docs: .. code-block:: sh $ /tmp/hack-zope.security/bin/easy_install Sphinx ... $ cd docs $ PATH=/tmp/hack-zope.security/bin:$PATH make html sphinx-build -b html -d _build/doctrees . _build/html ... build succeeded. Build finished. The HTML pages are in _build/html. You can also test the code snippets in the documentation: .. code-block:: sh $ PATH=/tmp/hack-zope.security/bin:$PATH make doctest sphinx-build -b doctest -d _build/doctrees . _build/doctest ... running tests... Document: api/zcml ------------------ 1 items passed all tests: 23 tests in default 23 tests in 1 items. 23 passed and 0 failed. Test passed. Document: api/proxy ------------------- 1 items passed all tests: 11 tests in default 11 tests in 1 items. 11 passed and 0 failed. Test passed. 1 items passed all tests: 1 tests in default (cleanup code) 1 tests in 1 items. 1 passed and 0 failed. Test passed. Document: api/permission ------------------------ 1 items passed all tests: 35 tests in default 35 tests in 1 items. 35 passed and 0 failed. Test passed. 1 items passed all tests: 1 tests in default (cleanup code) 1 tests in 1 items. 1 passed and 0 failed. Test passed. Document: api/checker --------------------- 1 items passed all tests: 356 tests in default 356 tests in 1 items. 356 passed and 0 failed. Test passed. Document: api/decorator ----------------------- 1 items passed all tests: 53 tests in default 53 tests in 1 items. 53 passed and 0 failed. Test passed. 1 items passed all tests: 1 tests in default (cleanup code) 1 tests in 1 items. 1 passed and 0 failed. Test passed. Doctest summary =============== 478 tests 0 failures in tests 0 failures in setup code 0 failures in cleanup code Using :mod:`zc.buildout` ######################## Setting up the buildout ----------------------- :mod:`zope.security` ships with its own :file:`buildout.cfg` file and :file:`bootstrap.py` for setting up a development buildout: .. code-block:: sh $ /path/to/python2.6 bootstrap.py ... Generated script '.../bin/buildout' $ bin/buildout Develop: '/home/jrandom/projects/Zope/BTK/security/.' ... Running the tests ----------------- You can now run the tests: .. code-block:: sh $ bin/test --all Running zope.testing.testrunner.layer.UnitTests tests: Set up zope.testing.testrunner.layer.UnitTests in 0.000 seconds. Ran 643 tests with 0 failures and 0 errors in 0.000 seconds. Tearing down left over layers: Tear down zope.testing.testrunner.layer.UnitTests in 0.000 seconds. Using :mod:`tox` ################ Running Tests on Multiple Python Versions ----------------------------------------- `tox `_ is a Python-based test automation tool designed to run tests against multiple Python versions. It creates a ``virtualenv`` for each configured version, installs the current package and configured dependencies into each ``virtualenv``, and then runs the configured commands. :mod:`zope.security` configures the following :mod:`tox` environments via its ``tox.ini`` file: - The ``py26``, ``py27``, ``py33``, ``py34``, and ``pypy`` environments builds a ``virtualenv`` with the appropriate interpreter, installs :mod:`zope.security` and dependencies, and runs the tests via ``python setup.py test -q``. - The ``py27-pure`` and ``py33-pure`` environments build a ``virtualenv`` with the appropriate interpreter, installs :mod:`zope.security` and dependencies **without compiling C extensions**, and runs the tests via ``python setup.py test -q``. - The ``coverage`` environment builds a ``virtualenv`` with ``python2.6``, installs :mod:`zope.security`, installs :mod:`nose` and :mod:`coverage`, and runs ``nosetests`` with statement coverage. - The ``docs`` environment builds a virtualenv with ``python2.6``, installs :mod:`zope.security`, installs ``Sphinx`` and dependencies, and then builds the docs and exercises the doctest snippets. This example requires that you have a working ``python2.6`` on your path, as well as installing ``tox``: .. code-block:: sh $ tox -e py26 GLOB sdist-make: .../zope.security/setup.py py26 sdist-reinst: .../zope.security/.tox/dist/zope.security-4.0.2dev.zip py26 runtests: commands[0] ................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... ---------------------------------------------------------------------- Ran 643 tests in 0.000s OK ___________________________________ summary ____________________________________ py26: commands succeeded congratulations :) Running ``tox`` with no arguments runs all the configured environments, including building the docs and testing their snippets: .. code-block:: sh $ tox GLOB sdist-make: .../zope.security/setup.py py26 sdist-reinst: .../zope.security/.tox/dist/zope.security-4.0.2dev.zip py26 runtests: commands[0] ... Doctest summary =============== 478 tests 0 failures in tests 0 failures in setup code 0 failures in cleanup code build succeeded. ___________________________________ summary ____________________________________ py26: commands succeeded py27: commands succeeded py27-pure: commands succeeded pypy: commands succeeded py32: commands succeeded py33: commands succeeded py33-pure: commands succeeded py34: commands succeeded coverage: commands succeeded docs: commands succeeded congratulations :) Contributing to :mod:`zope.security` #################################### Submitting a Bug Report ----------------------- :mod:`zope.security` tracks its bugs on Github: https://github.com/zopefoundation/zope.security/issues Please submit bug reports and feature requests there. Sharing Your Changes -------------------- .. note:: Please ensure that all tests are passing before you submit your code. If possible, your submission should include new tests for new features or bug fixes, although it is possible that you may have tested your new code by updating existing tests. If have made a change you would like to share, the best route is to fork the Githb repository, check out your fork, make your changes on a branch in your fork, and push it. You can then submit a pull request from your branch: https://github.com/zopefoundation/zope.security/pulls If you branched the code from Launchpad using Bazaar, you have another option: you can "push" your branch to Launchpad: .. code-block:: sh $ bzr push lp:~jrandom/zope.security/cool_feature After pushing your branch, you can link it to a bug report on Github, or request that the maintainers merge your branch using the Launchpad "merge request" feature. zope.security-4.0.3/MANIFEST.in0000664000175000017500000000024212450532147017246 0ustar tseavertseaver00000000000000include *.rst include *.txt recursive-include docs * recursive-include src * global-exclude *.dll global-exclude *.pyc global-exclude *.pyo global-exclude *.so zope.security-4.0.3/rtd.txt0000664000175000017500000000017212462242041017036 0ustar tseavertseaver00000000000000repoze.sphinx.autointerface Sphinx zope.component zope.configuration zope.interface zope.location zope.proxy zope.testing