summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTres Seaver <tseaver@palladion.com>2008-02-23 00:56:08 +0000
committerTres Seaver <tseaver@palladion.com>2008-02-23 00:56:08 +0000
commit1ec06eba414a6712589193667130a61ca5da7590 (patch)
tree7ff20f62d57f41308fdf67799f315bc9ece71c83
parent3d47f88c83954c76a677edd9a7ef4dc09cd376a2 (diff)
downloadzope-security-1ec06eba414a6712589193667130a61ca5da7590.tar.gz
Clear out 3.4.0 version of code.
-rw-r--r--src/zope/security/DEPENDENCIES.cfg6
-rw-r--r--src/zope/security/README.txt340
-rw-r--r--src/zope/security/SETUP.cfg9
-rw-r--r--src/zope/security/__init__.py26
-rw-r--r--src/zope/security/_definitions.py29
-rw-r--r--src/zope/security/_proxy.c1010
-rw-r--r--src/zope/security/_zope_security_checker.c605
-rw-r--r--src/zope/security/adapter.py134
-rw-r--r--src/zope/security/checker.py735
-rw-r--r--src/zope/security/decorator.py198
-rw-r--r--src/zope/security/examples/sandbox.py318
-rw-r--r--src/zope/security/examples/sandbox_security.py204
-rw-r--r--src/zope/security/interfaces.py321
-rw-r--r--src/zope/security/management.py144
-rw-r--r--src/zope/security/meta.zcml24
-rw-r--r--src/zope/security/permission.py64
-rw-r--r--src/zope/security/proxy.py73
-rw-r--r--src/zope/security/setup.py22
-rw-r--r--src/zope/security/simplepolicies.py61
-rw-r--r--src/zope/security/testing.py42
-rw-r--r--src/zope/security/tests/__init__.py2
-rw-r--r--src/zope/security/tests/test_adapter.py28
-rw-r--r--src/zope/security/tests/test_checker.py629
-rw-r--r--src/zope/security/tests/test_decorator.py28
-rw-r--r--src/zope/security/tests/test_management.py131
-rw-r--r--src/zope/security/tests/test_permission.py31
-rw-r--r--src/zope/security/tests/test_proxy.py447
-rw-r--r--src/zope/security/tests/test_set_checkers.py219
-rw-r--r--src/zope/security/tests/test_simpleinteraction.py81
-rw-r--r--src/zope/security/tests/test_standard_checkers.py498
-rw-r--r--src/zope/security/untrustedinterpreter.txt220
-rw-r--r--src/zope/security/untrustedpython/__init__.py1
-rw-r--r--src/zope/security/untrustedpython/builtins.py126
-rw-r--r--src/zope/security/untrustedpython/builtins.txt114
-rw-r--r--src/zope/security/untrustedpython/interpreter.py78
-rw-r--r--src/zope/security/untrustedpython/interpreter.txt112
-rw-r--r--src/zope/security/untrustedpython/rcompile.py97
-rw-r--r--src/zope/security/untrustedpython/rcompile.txt128
-rw-r--r--src/zope/security/untrustedpython/tests.py36
-rw-r--r--src/zope/security/zcml.py146
40 files changed, 0 insertions, 7517 deletions
diff --git a/src/zope/security/DEPENDENCIES.cfg b/src/zope/security/DEPENDENCIES.cfg
deleted file mode 100644
index 5fc1057..0000000
--- a/src/zope/security/DEPENDENCIES.cfg
+++ /dev/null
@@ -1,6 +0,0 @@
-RestrictedPython
-zope.exceptions
-zope.interface
-zope.proxy
-zope.testing
-zope.thread
diff --git a/src/zope/security/README.txt b/src/zope/security/README.txt
deleted file mode 100644
index 4940503..0000000
--- a/src/zope/security/README.txt
+++ /dev/null
@@ -1,340 +0,0 @@
-==============
-Zope3 Security
-==============
-
-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::
-
- class SimulationSecurityPolicy:
-
- implements(ISecurityPolicy)
-
- 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 <hazmat at objectrealms.net>
-- Guido Wesdorp <guido at infrae.com>
-- Marius Gedminas <marius at pov.lt>
-
diff --git a/src/zope/security/SETUP.cfg b/src/zope/security/SETUP.cfg
deleted file mode 100644
index f57d6f5..0000000
--- a/src/zope/security/SETUP.cfg
+++ /dev/null
@@ -1,9 +0,0 @@
-# Extension information for zpkg.
-
-<extension _proxy>
- source _proxy.c
-</extension>
-
-<extension _zope_security_checker>
- source _zope_security_checker.c
-</extension>
diff --git a/src/zope/security/__init__.py b/src/zope/security/__init__.py
deleted file mode 100644
index 18360ed..0000000
--- a/src/zope/security/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.0 (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
-
-$Id$
-
-"""
-
-import zope.deferredimport
-
-zope.deferredimport.define(
- checkPermission = 'zope.security.management:checkPermission',
- canWrite = 'zope.security.checker:canWrite',
- canAccess = 'zope.security.checker:canAccess',
- )
diff --git a/src/zope/security/_definitions.py b/src/zope/security/_definitions.py
deleted file mode 100644
index aa0d445..0000000
--- a/src/zope/security/_definitions.py
+++ /dev/null
@@ -1,29 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2005 Zope Corporation 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
-
-import zope.security.interfaces
-
-thread_local = threading.local()
-
-class system_user(object):
- zope.interface.classProvides(zope.security.interfaces.IPrincipal)
- id = u'zope.security.management.system_user'
- title = u'Special System User that typically has all permissions'
- description = u''
diff --git a/src/zope/security/_proxy.c b/src/zope/security/_proxy.c
deleted file mode 100644
index b0e3a81..0000000
--- a/src/zope/security/_proxy.c
+++ /dev/null
@@ -1,1010 +0,0 @@
-/*****************************************************************************
-*
-* Copyright (c) 2003, 2004 Zope Corporation 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
-
-$Id$
-*/
-
-#include <Python.h>
-#include "zope.proxy/proxy.h"
-
-static PyObject *__class__str = 0, *__name__str = 0, *__module__str = 0;
-
-#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);
-DECLARE_STRING(op_idiv);
-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)
-{
- if (visit(self->proxy.proxy_object, arg) < 0)
- return -1;
- if (visit(self->proxy_checker, arg) < 0)
- return -1;
- 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 = PyString_AsString(name);
- if (sname == NULL)
- goto err;
-
- module = PyObject_GetAttr(klass, __module__str);
- if (module != NULL) {
- smodule = PyString_AsString(module);
- if (smodule == NULL)
- goto err;
- result = PyString_FromFormat("<security proxied %s.%s instance at %p>",
- smodule, sname, object);
- }
- else {
- PyErr_Clear();
- result = PyString_FromFormat("<security proxied %s instance at %p>",
- 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;
-}
-
-static int
-proxy_compare(SecurityProxy *self, PyObject *other)
-{
- return PyObject_Compare(self->proxy.proxy_object, other);
-}
-
-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(long)
-NUMBER_METHOD(float)
-NUMBER_METHOD(oct)
-NUMBER_METHOD(hex)
-
-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)
-BINOP(div, PyNumber_Divide)
-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)
-
-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;
-}
-
-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(long, call_long)
-UNOP(float, call_float)
-UNOP(oct, call_oct)
-UNOP(hex, call_hex)
-
-INPLACE(add, PyNumber_InPlaceAdd)
-INPLACE(sub, PyNumber_InPlaceSubtract)
-INPLACE(mul, PyNumber_InPlaceMultiply)
-INPLACE(div, PyNumber_InPlaceDivide)
-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 int
-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, int 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, int 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, int start, int 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, int i, int 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 */
- proxy_div, /* nb_divide */
- 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 */
- proxy_coerce, /* nb_coerce */
- proxy_int, /* nb_int */
- proxy_long, /* nb_long */
- proxy_float, /* nb_float */
- proxy_oct, /* nb_oct */
- proxy_hex, /* nb_hex */
-
- /* 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 */
- proxy_idiv, /* nb_inplace_divide */
- 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 = {
- (inquiry)proxy_length, /* sq_length */
- 0, /* sq_concat */
- 0, /* sq_repeat */
- (intargfunc)proxy_igetitem, /* sq_item */
- (intintargfunc)proxy_slice, /* sq_slice */
- (intobjargproc)proxy_isetitem, /* sq_ass_item */
- (intintobjargproc)proxy_ass_slice, /* sq_ass_slice */
- (objobjproc)proxy_contains, /* sq_contains */
-};
-
-static PyMappingMethods
-proxy_as_mapping = {
- (inquiry)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\
-";
-
-statichere PyTypeObject
-SecurityProxyType = {
- PyObject_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 */
- (cmpfunc)proxy_compare, /* tp_compare */
- (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 */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES |
- Py_TPFLAGS_HAVE_GC, /* tp_flags */
- 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 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}
-};
-
-static char
-module___doc__[] = "Security proxy implementation.";
-
-void
-init_proxy(void)
-{
- PyObject *m;
-
- if (Proxy_Import() < 0)
- return;
-
-#define INIT_STRING(S) \
-if((str_##S = PyString_InternFromString(#S)) == NULL) return
-#define INIT_STRING_OP(S) \
-if((str_op_##S = PyString_InternFromString("__" #S "__")) == NULL) return
-
- 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);
- INIT_STRING_OP(idiv);
- 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 = PyString_FromString("__class__");
- if (! __class__str) return;
-
- __name__str = PyString_FromString("__name__");
- if (! __name__str) return;
-
- __module__str = PyString_FromString("__module__");
- if (! __module__str) return;
-
- SecurityProxyType.ob_type = &PyType_Type;
- SecurityProxyType.tp_alloc = PyType_GenericAlloc;
- SecurityProxyType.tp_free = _PyObject_GC_Del;
- SecurityProxyType.tp_base = &ProxyType;
- if (PyType_Ready(&SecurityProxyType) < 0)
- return;
-
- m = Py_InitModule3("_proxy", module_functions, module___doc__);
- if (m == NULL)
- return;
-
- Py_INCREF(&SecurityProxyType);
- PyModule_AddObject(m, "_Proxy", (PyObject *)&SecurityProxyType);
-}
diff --git a/src/zope/security/_zope_security_checker.c b/src/zope/security/_zope_security_checker.c
deleted file mode 100644
index 44eaf2c..0000000
--- a/src/zope/security/_zope_security_checker.c
+++ /dev/null
@@ -1,605 +0,0 @@
-/*
-
- Copyright (c) 2004 Zope Corporation and Contributors.
- All Rights Reserved.
-
- This software is subject to the provisions of the Zope Public License,
- Version 2.0 (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 <Python.h>
-
-static PyObject *_checkers, *_defaultChecker, *_available_by_default, *NoProxy;
-static PyObject *Proxy, *thread_local, *CheckerPublic;
-static PyObject *ForbiddenAttribute, *Unauthorized;
-
-#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 gere because we will use it for
- __setitem__, as describd 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 = (PyString_Check(name)
- && PyString_AS_STRING(name)[0] == '_'
- && PyString_AS_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__", PyString_AS_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*)(value->ob_type) == 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);
- self->ob_type->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 */ (inquiry)NULL,
- /* mp_subscript */ (binaryfunc)Checker_proxy,
- /* mp_ass_subscript */ (objobjargproc)Checker_check_int,
-};
-
-
-
-static PyTypeObject CheckerType = {
- PyObject_HEAD_INIT(NULL)
- /* ob_size */ 0,
- /* tp_name */ "zope.security.checker."
- "Checker",
- /* tp_basicsize */ sizeof(Checker),
- /* tp_itemsize */ 0,
- /* tp_dealloc */ (destructor)&Checker_dealloc,
- /* tp_print */ (printfunc)0,
- /* tp_getattr */ (getattrfunc)0,
- /* tp_setattr */ (setattrfunc)0,
- /* tp_compare */ (cmpfunc)0,
- /* tp_repr */ (reprfunc)0,
- /* tp_as_number */ 0,
- /* tp_as_sequence */ 0,
- /* tp_as_mapping */ &Checker_as_mapping,
- /* tp_hash */ (hashfunc)0,
- /* tp_call */ (ternaryfunc)0,
- /* tp_str */ (reprfunc)0,
- /* tp_getattro */ (getattrofunc)0,
- /* tp_setattro */ (setattrofunc)0,
- /* tp_as_buffer */ 0,
- /* tp_flags */ Py_TPFLAGS_DEFAULT
- | Py_TPFLAGS_BASETYPE
- | Py_TPFLAGS_HAVE_GC,
- /* tp_doc */ "Security checker",
- /* tp_traverse */ (traverseproc)Checker_traverse,
- /* tp_clear */ (inquiry)Checker_clear,
- /* tp_richcompare */ (richcmpfunc)0,
- /* tp_weaklistoffset */ (long)0,
- /* tp_iter */ (getiterfunc)0,
- /* tp_iternext */ (iternextfunc)0,
- /* tp_methods */ Checker_methods,
- /* tp_members */ 0,
- /* tp_getset */ Checker_getset,
- /* tp_base */ 0,
- /* tp_dict */ 0, /* internal use */
- /* tp_descr_get */ (descrgetfunc)0,
- /* tp_descr_set */ (descrsetfunc)0,
- /* tp_dictoffset */ 0,
- /* tp_init */ (initproc)Checker_init,
- /* tp_alloc */ (allocfunc)0,
- /* tp_new */ (newfunc)0,
- /* tp_free */ 0, /* Low-level free-mem routine */
- /* tp_is_gc */ (inquiry)0, /* For PyObject_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*)(object->ob_type));
- 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 PyMethodDef module_methods[] = {
- {"selectChecker", (PyCFunction)selectChecker, METH_O, selectChecker_doc},
- {NULL} /* Sentinel */
-};
-
-#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
-#define PyMODINIT_FUNC void
-#endif
-PyMODINIT_FUNC
-init_zope_security_checker(void)
-{
- PyObject* m;
-
- CheckerType.tp_new = PyType_GenericNew;
- if (PyType_Ready(&CheckerType) < 0)
- return;
-
- _defaultChecker = PyObject_CallFunction((PyObject*)&CheckerType, "{}");
- if (_defaultChecker == NULL)
- return;
-
-#define INIT_STRING(S) \
-if((str_##S = PyString_InternFromString(#S)) == NULL) return
-
- INIT_STRING(checkPermission);
- INIT_STRING(__Security_checker__);
- INIT_STRING(interaction);
-
- if ((_checkers = PyDict_New()) == NULL)
- return;
-
- NoProxy = PyObject_CallObject((PyObject*)&PyBaseObject_Type, NULL);
- if (NoProxy == NULL)
- return;
-
- if ((m = PyImport_ImportModule("zope.security._proxy")) == NULL) return;
- if ((Proxy = PyObject_GetAttrString(m, "_Proxy")) == NULL) return;
- Py_DECREF(m);
-
- if ((m = PyImport_ImportModule("zope.security._definitions")) == NULL) return;
- thread_local = PyObject_GetAttrString(m, "thread_local");
- if (thread_local == NULL) return;
- Py_DECREF(m);
-
- if ((m = PyImport_ImportModule("zope.security.interfaces")) == NULL) return;
- ForbiddenAttribute = PyObject_GetAttrString(m, "ForbiddenAttribute");
- if (ForbiddenAttribute == NULL) return;
- Unauthorized = PyObject_GetAttrString(m, "Unauthorized");
- if (Unauthorized == NULL) return;
- Py_DECREF(m);
-
- if ((m = PyImport_ImportModule("zope.security.checker")) == NULL) return;
- CheckerPublic = PyObject_GetAttrString(m, "CheckerPublic");
- if (CheckerPublic == NULL) return;
- Py_DECREF(m);
-
- if ((_available_by_default = PyList_New(0)) == NULL) return;
-
- m = Py_InitModule3("_zope_security_checker", module_methods,
- "C optimizations for zope.security.checker");
-
- if (m == NULL)
- return;
-
-#define EXPORT(N) Py_INCREF(N); PyModule_AddObject(m, #N, N)
-
- EXPORT(_checkers);
- EXPORT(NoProxy);
- EXPORT(_defaultChecker);
- EXPORT(_available_by_default);
-
- Py_INCREF(&CheckerType);
- PyModule_AddObject(m, "Checker", (PyObject *)&CheckerType);
-}
diff --git a/src/zope/security/adapter.py b/src/zope/security/adapter.py
deleted file mode 100644
index 2c9ddff..0000000
--- a/src/zope/security/adapter.py
+++ /dev/null
@@ -1,134 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 Zope Corporation 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
-
-$Id$
-"""
-
-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.
-
- see adapter.txt
- """
- # 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)
- else:
- 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:
-
- see adapter.txt
- """
- 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 = map(removeSecurityProxy, 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
-
-
-# BBB, entire class gone in 3.2
-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:
-
- see adapter.txt
- """
-
- 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])
diff --git a/src/zope/security/checker.py b/src/zope/security/checker.py
deleted file mode 100644
index d3b29aa..0000000
--- a/src/zope/security/checker.py
+++ /dev/null
@@ -1,735 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation 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.
-
-$Id$
-"""
-import os
-import sys
-import sets
-import types
-import datetime
-import decimal
-import pytz
-import weakref
-
-from zope.exceptions import DuplicationError
-import zope.interface.interface
-import zope.interface.interfaces
-import zope.interface.declarations
-from zope.interface import directlyProvides, Interface, implements
-from zope.interface.interfaces import IInterface, IDeclaration
-
-from zope.security.interfaces import IChecker, INameBasedChecker
-from zope.security.interfaces import ISecurityProxyFactory
-from zope.security.interfaces import Unauthorized, ForbiddenAttribute
-from zope.security._definitions import thread_local
-from zope.security._proxy import _Proxy as Proxy, getChecker
-
-if os.environ.get('ZOPE_WATCH_CHECKERS'):
- 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)
-
-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
-
-class Checker(object):
- implements(INameBasedChecker)
-
- 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.
-
- """
- assert isinstance(get_permissions, dict)
- self.get_permissions = get_permissions
- if set_permissions is not None:
- assert isinstance(set_permissions, dict)
- 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_getattr(self, object, name):
- 'See IChecker'
- self.check(object, 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)
-
- 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)
-
-
-
-# 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:
- s = str(cls.__name__)
- result.append(" - class: " + s)
- except:
- pass
- try:
- cls = type(self.obj)
- if hasattr(cls, "__module__"):
- s = "%s.%s" % (cls.__module__, cls.__name__)
- else:
- s = str(cls.__name__)
- result.append(" - type: " + s)
- except:
- 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:
- 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')
-
-# Now we wrap it in a security proxy so that it retains it's
-# identity when it needs to be security proxied.
-d={}
-CheckerPublic = Proxy(CheckerPublic, Checker(d))
-d['__reduce__'] = 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 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.
- """
-
- # 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
-
-def getCheckerForInstancesOf(class_):
- return _checkers.get(class_)
-
-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_, (type, types.ClassType, types.ModuleType)):
- 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:
- 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
-
-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
- ------------------ ------------------ -----------------------------------
- """
- implements(IChecker)
-
- 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, 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, 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
-
- def check(self, object, name):
- try:
- super(CheckerLoggingMixin, self).check(object, name)
- if self.verbosity > 1:
- if name in _available_by_default:
- print >> sys.stderr, (
- '[CHK] + Always available: %s on %r' % (name, object))
- else:
- print >> sys.stderr, (
- '[CHK] + Granted: %s on %r' % (name, object))
- except Unauthorized:
- print >> sys.stderr, (
- '[CHK] - Unauthorized: %s on %r' % (name, object))
- raise
- except ForbiddenAttribute:
- print >> sys.stderr, (
- '[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:
- print >> sys.stderr, (
- '[CHK] + Always available getattr: %s on %r'
- % (name, object))
- else:
- print >> sys.stderr, (
- '[CHK] + Granted getattr: %s on %r'
- % (name, object))
- except Unauthorized:
- print >> sys.stderr, (
- '[CHK] - Unauthorized getattr: %s on %r' % (name, object))
- raise
- except ForbiddenAttribute:
- print >> sys.stderr, (
- '[CHK] - Forbidden getattr: %s on %r' % (name, object))
- raise
-
- def check_setattr(self, object, name):
- try:
- super(CheckerLoggingMixin, self).check_setattr(object, name)
- if self.verbosity > 1:
- print >> sys.stderr, (
- '[CHK] + Granted setattr: %s on %r' % (name, object))
- except Unauthorized:
- print >> sys.stderr, (
- '[CHK] - Unauthorized setattr: %s on %r' % (name, object))
- raise
- except ForbiddenAttribute:
- print >> sys.stderr, (
- '[CHK] - Forbidden setattr: %s on %r' % (name, object))
- raise
-
-
-if WATCH_CHECKERS:
- 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__',
- ]
-
-_callableChecker = NamesChecker(['__str__', '__name__', '__call__'])
-_typeChecker = NamesChecker(
- ['__str__', '__name__', '__module__', '__bases__', '__mro__',
- '__implemented__'])
-_namedChecker = NamesChecker(['__name__'])
-
-_iteratorChecker = NamesChecker(['next', '__iter__'])
-
-_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)
-
-BasicTypes = BasicTypes({
- object: NoProxy,
- int: NoProxy,
- float: NoProxy,
- long: NoProxy,
- complex: NoProxy,
- types.NoneType: NoProxy,
- str: NoProxy,
- unicode: NoProxy,
- bool: NoProxy,
- datetime.timedelta: NoProxy,
- datetime.datetime: NoProxy,
- datetime.date: NoProxy,
- datetime.time: NoProxy,
- datetime.tzinfo: NoProxy,
- type(pytz.UTC): NoProxy,
-})
-
-# Available for tests. Located here so it can be kept in sync with BasicTypes.
-BasicTypes_examples = {
- object: object(),
- int: 65536,
- float: -1.4142,
- long: 65536l,
- complex: -1.4142j,
- types.NoneType: None,
- str: 'abc',
- unicode: u'uabc',
- 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)
-}
-
-
-class _Sequence(object):
- 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():
- 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__', ]),
- sets.Set: _setChecker,
- sets.ImmutableSet: _setChecker,
- 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__']),
- types.InstanceType: _instanceChecker,
- Proxy: NoProxy,
- type(weakref.ref(_Sequence())): NamesChecker(['__call__']),
- types.ClassType: _typeChecker,
- types.FunctionType: _callableChecker,
- types.MethodType: _callableChecker,
- types.BuiltinFunctionType: _callableChecker,
- types.BuiltinMethodType: _callableChecker,
- type(().__getslice__): _callableChecker, # slot description
- 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({}.iteritems()): _iteratorChecker,
- type({}.iterkeys()): _iteratorChecker,
- type({}.itervalues()): _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,
-}
-
-def _clear():
- _checkers.clear()
- _checkers.update(_default_checkers)
- _checkers.update(BasicTypes)
-
-_clear()
-
-try:
- from zope.testing.cleanup import addCleanUp
-except ImportError:
- pass
-else:
- addCleanUp(_clear)
-
diff --git a/src/zope/security/decorator.py b/src/zope/security/decorator.py
deleted file mode 100644
index 035b68d..0000000
--- a/src/zope/security/decorator.py
+++ /dev/null
@@ -1,198 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation 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.
-
-$Id$
-"""
-__docformat__ = "reStructuredText"
-
-from zope.proxy import getProxiedObject, ProxyBase
-from zope.proxy.decorator import SpecificationDecoratorBase
-from zope.security.checker import selectChecker, CombinedChecker
-from zope.security.proxy import Proxy, getChecker
-from zope.interface.declarations import ObjectSpecification
-
-class DecoratedSecurityCheckerDescriptor(object):
- """Descriptor for a Decorator that provides a decorated security checker.
-
- To illustrate, we'll create a class that will be proxied:
-
- >>> class Foo(object):
- ... a = 'a'
-
- and a class to proxy it that uses a decorated security checker:
-
- >>> class Wrapper(ProxyBase):
- ... b = 'b'
- ... __Security_checker__ = DecoratedSecurityCheckerDescriptor()
-
- Next we'll create and register a checker for `Foo`:
-
- >>> from zope.security.checker import NamesChecker, defineChecker
- >>> fooChecker = NamesChecker(['a'])
- >>> defineChecker(Foo, fooChecker)
-
- along with a checker for `Wrapper`:
-
- >>> wrapperChecker = NamesChecker(['b'])
- >>> defineChecker(Wrapper, wrapperChecker)
-
- Using `selectChecker()`, we can confirm that a `Foo` object uses
- `fooChecker`:
-
- >>> foo = Foo()
- >>> selectChecker(foo) is fooChecker
- True
- >>> fooChecker.check(foo, 'a')
- >>> fooChecker.check(foo, 'b') # doctest: +ELLIPSIS
- Traceback (most recent call last):
- ForbiddenAttribute: ('b', <zope.security.decorator.Foo object ...>)
-
- and that a `Wrapper` object uses `wrappeChecker`:
-
- >>> wrapper = Wrapper(foo)
- >>> selectChecker(wrapper) is wrapperChecker
- True
- >>> wrapperChecker.check(wrapper, 'b')
- >>> wrapperChecker.check(wrapper, 'a') # doctest: +ELLIPSIS
- Traceback (most recent call last):
- ForbiddenAttribute: ('a', <zope.security.decorator.Foo object ...>)
-
- (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:
-
- >>> checker = wrapper.__Security_checker__
- >>> type(checker)
- <class 'zope.security.checker.CombinedChecker'>
- >>> checker.check(wrapper, 'a')
- >>> checker.check(wrapper, 'b')
-
- The decorator checker will work even with security proxied objects. To
- illustrate, we'll proxify `foo`:
-
- >>> from zope.security.proxy import ProxyFactory
- >>> secure_foo = ProxyFactory(foo)
- >>> secure_foo.a
- 'a'
- >>> secure_foo.b # doctest: +ELLIPSIS
- Traceback (most recent call last):
- ForbiddenAttribute: ('b', <zope.security.decorator.Foo object ...>)
-
- when we wrap the secured `foo`:
-
- >>> wrapper = Wrapper(secure_foo)
-
- we still get a combined checker:
-
- >>> checker = wrapper.__Security_checker__
- >>> type(checker)
- <class 'zope.security.checker.CombinedChecker'>
- >>> 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:
-
- >>> 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:
-
- >>> wrapper = Wrapper(foo)
- >>> wrapper.__Security_checker__ is wrapperChecker
- True
-
- When the proxied object has a checker but the wrapper doesn't:
-
- >>> 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:
-
- >>> wrapper.__Security_checker__ is fooChecker
- True
-
- Finally, if neither the wrapper not the proxied have checkers:
-
- >>> del _checkers[Foo]
- >>> defineChecker(Foo, NoProxy)
- >>> selectChecker(foo) is None
- True
- >>> selectChecker(wrapper) is None
- True
-
- the decorator doesn't have a checker:
-
- >>> wrapper.__Security_checker__ is None
- True
-
- """
- 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:
- 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."""
-
-
diff --git a/src/zope/security/examples/sandbox.py b/src/zope/security/examples/sandbox.py
deleted file mode 100644
index 2ef25c2..0000000
--- a/src/zope/security/examples/sandbox.py
+++ /dev/null
@@ -1,318 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation 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.
-
-$Id$
-"""
-import time, random
-
-from zope.interface import Interface, implements
-
-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__
-
-
-class Agent(Identity):
- implements(IAgent)
-
- 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
-
-
-class Sandbox(Identity):
- """
- see ISandbox doc
- """
- implements(ISandbox)
-
- 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)
- )
-
-class Service(object):
- implements(IService)
- 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, 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, e:
- print '-- Exception --'
- print 'moving "%s" from "%s" to "%s"' %(a, h,` 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()
diff --git a/src/zope/security/examples/sandbox_security.py b/src/zope/security/examples/sandbox_security.py
deleted file mode 100644
index a5e8d39..0000000
--- a/src/zope/security/examples/sandbox_security.py
+++ /dev/null
@@ -1,204 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation 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
-
-$Id$
-"""
-import sandbox
-from zope.security.interfaces import IParticipation
-from zope.security import checker, management, simplepolicies
-from zope.interface import implements
-
-
-# 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
-
-
-class AgentParticipation(object):
- """Agent Participation during the Simulation.
-
- A very simple participation that is specific to the simulations.
- """
-
- implements(IParticipation)
-
- 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()
diff --git a/src/zope/security/interfaces.py b/src/zope/security/interfaces.py
deleted file mode 100644
index 0376c74..0000000
--- a/src/zope/security/interfaces.py
+++ /dev/null
@@ -1,321 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 Zope Corporation 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.
-
-$Id$
-"""
-
-from zope.interface import Interface, Attribute, implements
-from zope.interface.common.interfaces import IException, IAttributeError
-from zope.schema import Text, TextLine
-from zope.i18nmessageid import MessageFactory
-_ = MessageFactory('zope')
-
-class IUnauthorized(IException):
- pass
-
-class Unauthorized(Exception):
- """Some user wasn't allowed to access a resource"""
-
- implements(IUnauthorized)
-
-
-class IForbidden(IException):
- pass
-
-class Forbidden(Exception):
- """A resource cannot be accessed under any circumstances
- """
- implements(IForbidden)
-
-class IForbiddenAttribute(IForbidden, IAttributeError):
- pass
-
-class ForbiddenAttribute(Forbidden, AttributeError):
- """An attribute is unavailable because it is forbidden (private)
- """
- implements(IForbiddenAttribute)
-
-
-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.
-
- Arguments:
- permission -- A permission name
- object -- The object being accessed according to the permission
- interaction -- An interaction, which provides 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 chack 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)
diff --git a/src/zope/security/management.py b/src/zope/security/management.py
deleted file mode 100644
index 3a106bf..0000000
--- a/src/zope/security/management.py
+++ /dev/null
@@ -1,144 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation 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
-
-$Id$
-"""
-
-
-import zope.interface
-import zope.thread
-
-import zope.security.interfaces
-
-from zope.security.checker import CheckerPublic
-from zope.security._definitions import thread_local, system_user
-from zope.security.simplepolicies import ParanoidSecurityPolicy
-
-_defaultPolicy = ParanoidSecurityPolicy
-
-zope.interface.moduleProvides(
- zope.security.interfaces.ISecurityManagement,
- zope.security.interfaces.IInteractionManagement)
-
-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:
- def addCleanUp(arg):
- pass
-
-addCleanUp(_clear)
-
-#
-# 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 zope.security.interfaces.NoInteraction
-
-def newInteraction(*participations):
- """Start a new interaction."""
-
- if queryInteraction() is not None:
- raise AssertionError("newInteraction called"
- " while another interaction is active.")
-
- interaction = getSecurityPolicy()(*participations)
-
- thread_local.interaction = interaction
-
-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.
-
- Arguments:
- permission -- A permission name
- object -- The object being accessed according to the permission
- interaction -- An interaction, which provides 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:
- interaction = thread_local.interaction
- return interaction.checkPermission(permission, object)
-
-addCleanUp(endInteraction)
diff --git a/src/zope/security/meta.zcml b/src/zope/security/meta.zcml
deleted file mode 100644
index c3f54e2..0000000
--- a/src/zope/security/meta.zcml
+++ /dev/null
@@ -1,24 +0,0 @@
-<configure
- xmlns="http://namespaces.zope.org/zope"
- xmlns:meta="http://namespaces.zope.org/meta">
-
- <meta:directive
- namespace="http://namespaces.zope.org/zope"
- name="permission"
- schema=".zcml.IPermissionDirective"
- handler=".zcml.permission" />
-
- <meta:directive
- name="securityPolicy"
- namespace="http://namespaces.zope.org/zope"
- schema=".zcml.ISecurityPolicyDirective"
- handler=".zcml.securityPolicy"
- />
-
- <meta:directive
- name="redefinePermission"
- namespace="http://namespaces.zope.org/meta"
- schema=".zcml.IRedefinePermission"
- handler=".zcml.redefinePermission" />
-
-</configure>
diff --git a/src/zope/security/permission.py b/src/zope/security/permission.py
deleted file mode 100644
index 1999f85..0000000
--- a/src/zope/security/permission.py
+++ /dev/null
@@ -1,64 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002 Zope Corporation 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
-
-$Id$
-"""
-__docformat__ = "reStructuredText"
-
-from zope.interface import implements
-from zope.component import queryUtility, getUtilitiesFor
-from zope.security.checker import CheckerPublic
-from zope.security.interfaces import IPermission
-
-class Permission(object):
- implements(IPermission)
-
- 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.
-
- >>> from zope.component import provideUtility
- >>> provideUtility(Permission('x'), IPermission, 'x')
-
- >>> checkPermission(None, 'x')
- >>> checkPermission(None, 'y')
- Traceback (most recent call last):
- ...
- ValueError: ('Undefined permission id', 'y')
- """
- 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
-
- >>> from zope.component import provideUtility
- >>> provideUtility(Permission('x'), IPermission, 'x')
- >>> provideUtility(Permission('y'), IPermission, 'y')
-
- >>> ids = list(allPermissions(None))
- >>> ids.sort()
- >>> ids
- [u'x', u'y']
- """
- for id, permission in getUtilitiesFor(IPermission, context):
- if id != u'zope.Public':
- yield id
diff --git a/src/zope/security/proxy.py b/src/zope/security/proxy.py
deleted file mode 100644
index acd3a91..0000000
--- a/src/zope/security/proxy.py
+++ /dev/null
@@ -1,73 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation 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.
-
-$Id$
-"""
-__docformat__ = 'restructuredtext'
-
-from zope.security._proxy import getChecker, getObject
-from zope.security._proxy import _Proxy as Proxy
-
-removeSecurityProxy = getObject
-
-# This import represents part of the API for this module
-from zope.security.checker import ProxyFactory
-
-def getTestProxyItems(proxy):
- """Try to get checker names and permissions for testing
-
- If this succeeds, a sorted sequence of items is returned,
- otherwise, None is returned.
- """
- checker = getChecker(proxy)
- items = checker.get_permissions.items()
- items.sort()
- return items
-
-
-builtin_isinstance = isinstance
-def isinstance(object, cls):
- """Test whether an object is an instance of a type.
-
- This works even if the object is security proxied:
-
- >>> 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
-
- """
-
- # The removeSecurityProxy call is OK here because it is *only*
- # being used for isinstance
-
- return builtin_isinstance(removeSecurityProxy(object), cls)
diff --git a/src/zope/security/setup.py b/src/zope/security/setup.py
deleted file mode 100644
index 4ecc3be..0000000
--- a/src/zope/security/setup.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#! /usr/bin/env python
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation 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
-
-$Id$
-"""
-from distutils.core import setup, Extension
-
-setup(name="_Proxy", version = "0.1",
- ext_modules=[Extension("_Proxy", ["_Proxy.c"])])
diff --git a/src/zope/security/simplepolicies.py b/src/zope/security/simplepolicies.py
deleted file mode 100644
index 3cca0b9..0000000
--- a/src/zope/security/simplepolicies.py
+++ /dev/null
@@ -1,61 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation 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.
-
-$Id$
-"""
-import zope.interface
-from zope.security.checker import CheckerPublic
-from zope.security.interfaces import IInteraction, ISecurityPolicy
-from zope.security._definitions import system_user
-
-class ParanoidSecurityPolicy(object):
- zope.interface.implements(IInteraction)
- zope.interface.classProvides(ISecurityPolicy)
-
- 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
-
-class PermissiveSecurityPolicy(ParanoidSecurityPolicy):
- """Allow all access."""
- zope.interface.classProvides(ISecurityPolicy)
-
- def checkPermission(self, permission, object):
- return True
diff --git a/src/zope/security/testing.py b/src/zope/security/testing.py
deleted file mode 100644
index 804e493..0000000
--- a/src/zope/security/testing.py
+++ /dev/null
@@ -1,42 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 Zope Corporation 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.
-
-$Id$
-"""
-
-from zope import interface
-from zope.security import interfaces
-
-class Principal:
-
- interface.implements(interfaces.IPrincipal)
-
- 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)
-
-class Participation:
-
- interface.implements(interfaces.IParticipation)
-
- def __init__(self, principal):
- self.principal = principal
- self.interaction = None
diff --git a/src/zope/security/tests/__init__.py b/src/zope/security/tests/__init__.py
deleted file mode 100644
index b711d36..0000000
--- a/src/zope/security/tests/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-#
-# This file is necessary to make this directory a package.
diff --git a/src/zope/security/tests/test_adapter.py b/src/zope/security/tests/test_adapter.py
deleted file mode 100644
index 88465f6..0000000
--- a/src/zope/security/tests/test_adapter.py
+++ /dev/null
@@ -1,28 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 Zope Corporation 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.
-#
-##############################################################################
-"""
-$Id$
-"""
-import unittest
-from zope.testing.doctestunit import DocTestSuite
-
-
-def test_suite():
- return unittest.TestSuite((
- DocTestSuite('zope.security.adapter'),
- ))
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='test_suite')
diff --git a/src/zope/security/tests/test_checker.py b/src/zope/security/tests/test_checker.py
deleted file mode 100644
index f739c71..0000000
--- a/src/zope/security/tests/test_checker.py
+++ /dev/null
@@ -1,629 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation 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 Checker tests
-
-$Id$
-"""
-from unittest import TestCase, TestSuite, main, makeSuite
-from zope.interface import implements
-from zope.interface.verify import verifyObject
-from zope.testing.cleanup import CleanUp
-from zope.proxy import getProxiedObject
-from zope.security.interfaces import ISecurityPolicy, Unauthorized
-from zope.security.interfaces import Forbidden, ForbiddenAttribute
-from zope.security.management import setSecurityPolicy, newInteraction
-from zope.security.management import endInteraction, getInteraction
-from zope.security.proxy import removeSecurityProxy, getChecker, Proxy
-from zope.security.checker import defineChecker, undefineChecker, ProxyFactory
-from zope.security.checker import canWrite, canAccess
-from zope.security.checker import Checker, NamesChecker, CheckerPublic
-from zope.security.checker import BasicTypes, _checkers, NoProxy, _clear
-import types, pickle
-
-class SecurityPolicy(object):
- implements(ISecurityPolicy)
-
- def checkPermission(self, permission, object):
- 'See ISecurityPolicy'
- return permission == 'test_allowed'
-
-class RecordedSecurityPolicy(object):
- implements(ISecurityPolicy)
-
- def __init__(self):
- self._checked = []
- self.permissions = {}
-
- def checkPermission(self, permission, object):
- 'See ISecurityPolicy'
- self._checked.append(permission)
- return self.permissions.get(permission, True)
-
- def checkChecked(self, checked):
- res = self._checked == checked
- self._checked = []
- return res
-
-class TransparentProxy(object):
- def __init__(self, ob):
- self._ob = ob
-
- def __getattribute__(self, name):
- ob = object.__getattribute__(self, '_ob')
- return getattr(ob, name)
-
-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)
-
-
-class Test(TestCase, CleanUp):
-
- def setUp(self):
- CleanUp.setUp(self)
- self.__oldpolicy = setSecurityPolicy(SecurityPolicy)
- newInteraction()
-
- def tearDown(self):
- endInteraction()
- setSecurityPolicy(self.__oldpolicy)
- CleanUp.tearDown(self)
-
- def test_typesAcceptedByDefineChecker(self):
- class ClassicClass:
- __metaclass__ = types.ClassType
- class NewStyleClass:
- __metaclass__ = type
- import zope.security
- not_a_type = object()
- defineChecker(ClassicClass, NamesChecker())
- defineChecker(NewStyleClass, NamesChecker())
- defineChecker(zope.security, NamesChecker())
- self.assertRaises(TypeError,
- defineChecker, not_a_type, NamesChecker())
-
- # check_getattr cases:
- #
- # - no attribute there
- # - method
- # - allow and disallow by permission
- def test_check_getattr(self):
-
- 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')
-
- def test_check_setattr(self):
-
- 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')
-
- def test_proxy(self):
- checker = NamesChecker(())
-
- from zope.security.checker import BasicTypes_examples
- rocks = tuple(BasicTypes_examples.values())
- for rock in rocks:
- proxy = checker.proxy(rock)
- self.failUnless(proxy is rock, (rock, type(proxy)))
-
- for class_ in OldInst, NewInst:
- inst = class_()
-
- for ob in inst, class_:
- proxy = checker.proxy(ob)
- self.failUnless(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)
- #
- #for ob in inst, TransparentProxy(inst):
- # proxy = checker.proxy(ob)
- # self.failUnless(removeSecurityProxy(proxy) is ob)
- #
- # checker = getChecker(proxy)
- # self.failUnless(checker is special,
- # checker.get_permissions)
- #
- # proxy2 = checker.proxy(proxy)
- # self.failUnless(proxy2 is proxy, [proxy, proxy2])
-
- def testLayeredProxies(self):
- """Tests that a Proxy will not be re-proxied."""
- 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.assert_(type(proxy1) is Proxy)
- self.assert_(getProxiedObject(proxy1) is base)
-
- # proxy is a proxy, so we don't expect to get another
- proxy2 = checker.proxy(proxy1)
- self.assert_(proxy2 is proxy1)
- self.assert_(getProxiedObject(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)
-
- def test_setattr(self):
- 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):
- class SomeClass(object):
- pass
- import zope.security
- checker = NamesChecker()
- specific_checker = NamesChecker()
- checker_as_magic_attr = NamesChecker()
-
- obj = SomeClass()
-
- proxy = ProxyFactory(obj)
- self.assert_(type(proxy) is Proxy)
- from zope.security.checker import _defaultChecker
- self.assert_(getChecker(proxy) is _defaultChecker)
-
- defineChecker(SomeClass, checker)
-
- proxy = ProxyFactory(obj)
- self.assert_(type(proxy) is Proxy)
- self.assert_(getChecker(proxy) is checker)
-
- obj.__Security_checker__ = checker_as_magic_attr
-
- proxy = ProxyFactory(obj)
- self.assert_(type(proxy) is Proxy)
- self.assert_(getChecker(proxy) is checker_as_magic_attr)
-
- proxy = ProxyFactory(obj, specific_checker)
- self.assert_(type(proxy) is Proxy)
- self.assert_(getChecker(proxy) is specific_checker)
-
- def test_define_and_undefineChecker(self):
- class SomeClass(object):
- pass
- obj = SomeClass()
-
- checker = NamesChecker()
- from zope.security.checker import _defaultChecker, selectChecker
- self.assert_(selectChecker(obj) is _defaultChecker)
- defineChecker(SomeClass, checker)
- self.assert_(selectChecker(obj) is checker)
- undefineChecker(SomeClass)
- self.assert_(selectChecker(obj) is _defaultChecker)
-
- def test_ProxyFactory_using_proxy(self):
- class SomeClass(object):
- pass
- obj = SomeClass()
- checker = NamesChecker()
- proxy1 = ProxyFactory(obj)
-
- proxy2 = ProxyFactory(proxy1)
- self.assert_(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.assert_(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.
- 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.assert_(canWrite(obj, 'foo'))
- self.assert_(canAccess(obj, 'foo'))
-
- # ...may access, but not write, bar...
- self.assert_(not canWrite(obj, 'bar'))
- self.assert_(canAccess(obj, 'bar'))
-
- # ...and may access baz.
- self.assert_(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.assert_(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.assert_(not canWrite(obj, 'bing'))
- self.assertRaises(Forbidden, canAccess, obj, 'bing')
-
-class TestCheckerPublic(TestCase):
-
- def test_that_pickling_CheckerPublic_retains_identity(self):
- self.assert_(pickle.loads(pickle.dumps(CheckerPublic))
- is
- CheckerPublic)
-
- def test_that_CheckerPublic_identity_works_even_when_proxied(self):
- self.assert_(ProxyFactory(CheckerPublic) is CheckerPublic)
-
-
-class TestMixinDecoratedChecker(TestCase):
-
- def decoratedSetUp(self):
- self.policy = RecordedSecurityPolicy
- self._oldpolicy = setSecurityPolicy(self.policy)
- newInteraction()
- self.interaction = getInteraction()
- self.obj = object()
-
- def decoratedTearDown(self):
- endInteraction()
- setSecurityPolicy(self._oldpolicy)
-
- def check_checking_impl(self, checker):
- o = self.obj
- checker.check_getattr(o, 'both_get_set')
- self.assert_(self.interaction.checkChecked(['dc_get_permission']))
- checker.check_getattr(o, 'c_only')
- self.assert_(self.interaction.checkChecked(['get_permission']))
- checker.check_getattr(o, 'd_only')
- self.assert_(self.interaction.checkChecked(['dc_get_permission']))
- self.assertRaises(ForbiddenAttribute,
- checker.check_getattr, o,
- 'completely_different_attr')
- self.assert_(self.interaction.checkChecked([]))
- checker.check(o, '__str__')
- self.assert_(self.interaction.checkChecked(['get_permission']))
-
- checker.check_setattr(o, 'both_get_set')
- self.assert_(self.interaction.checkChecked(['dc_set_permission']))
- self.assertRaises(ForbiddenAttribute,
- checker.check_setattr, o, 'c_only')
- self.assert_(self.interaction.checkChecked([]))
- self.assertRaises(ForbiddenAttribute,
- checker.check_setattr, o, 'd_only')
- self.assert_(self.interaction.checkChecked([]))
-
- originalChecker = 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'}
-
- overridingChecker = Checker(decorationGetMap, decorationSetMap)
-
-class TestCombinedChecker(TestMixinDecoratedChecker, TestCase):
-
- def setUp(self):
- TestCase.setUp(self)
- self.decoratedSetUp()
-
- def tearDown(self):
- self.decoratedTearDown()
- TestCase.tearDown(self)
-
- def test_checking(self):
- 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.assert_(
- 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.security.checker import CombinedChecker
- from zope.security.interfaces import IChecker
- dc = CombinedChecker(self.overridingChecker, self.originalChecker)
- verifyObject(IChecker, dc)
-
-
-class TestBasicTypes(TestCase):
-
- def test(self):
- 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.assert_(MyType in _checkers)
-
- # If we clear the checkers, the type should still be there
- _clear()
- self.assert_(MyType in BasicTypes)
- self.assert_(MyType in _checkers)
-
- # Now delete the type from the dictionary, will also delete it from
- # the checkers
- del BasicTypes[MyType]
- self.assert_(MyType not in BasicTypes)
- self.assert_(MyType not in _checkers)
-
- # The quick way of adding new types is using update
- BasicTypes.update({MyType: NoProxy, MyType2: NoProxy})
- self.assert_(MyType in BasicTypes)
- self.assert_(MyType2 in BasicTypes)
- self.assert_(MyType in _checkers)
- self.assert_(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()
- keys.sort()
- self.assert_(bool in keys)
- self.assert_(int in keys)
- self.assert_(float in keys)
- self.assert_(str in keys)
- self.assert_(unicode in keys)
- self.assert_(object in keys)
- # ...
-
- # Finally, the ``clear()`` method has been deactivated to avoid
- # unwanted deletions.
- self.assertRaises(NotImplementedError, BasicTypes.clear)
-
-def test_suite():
- return TestSuite((
- makeSuite(Test),
- makeSuite(TestCheckerPublic),
- makeSuite(TestCombinedChecker),
- makeSuite(TestBasicTypes),
- ))
-
-if __name__=='__main__':
- main(defaultTest='test_suite')
diff --git a/src/zope/security/tests/test_decorator.py b/src/zope/security/tests/test_decorator.py
deleted file mode 100644
index 6067ce4..0000000
--- a/src/zope/security/tests/test_decorator.py
+++ /dev/null
@@ -1,28 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation 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.
-#
-##############################################################################
-"""Context Tests
-
-$Id$
-"""
-import unittest
-from zope.testing import doctest
-
-def test_suite():
- suite = doctest.DocTestSuite()
- suite.addTest(doctest.DocTestSuite('zope.security.decorator'))
- return suite
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/src/zope/security/tests/test_management.py b/src/zope/security/tests/test_management.py
deleted file mode 100644
index 63f0000..0000000
--- a/src/zope/security/tests/test_management.py
+++ /dev/null
@@ -1,131 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation 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 SecurityManagement
-
-$Id$
-"""
-
-import unittest
-
-from zope.interface.verify import verifyObject
-from zope.testing.cleanup import CleanUp
-
-
-class Test(CleanUp, unittest.TestCase):
-
- def test_import(self):
- 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.assert_(getSecurityPolicy() is policy)
-
- def test_query_new_end_restore_Interaction(self):
- from zope.security.management import queryInteraction
- self.assertEquals(queryInteraction(), None)
-
- from zope.security.management import newInteraction
-
- newInteraction()
-
- interaction = queryInteraction()
- self.assert_(interaction is not None)
- self.assertRaises(AssertionError, newInteraction)
-
- from zope.security.management import endInteraction
- endInteraction()
- self.assertEquals(queryInteraction(), None)
-
- from zope.security.management import restoreInteraction
- restoreInteraction()
- self.assert_(interaction is queryInteraction())
-
- endInteraction()
- self.assertEquals(queryInteraction(), None)
-
- endInteraction()
- self.assertEquals(queryInteraction(), None)
-
- newInteraction()
- self.assert_(queryInteraction() is not None)
-
- restoreInteraction() # restore to no interaction
- self.assert_(queryInteraction() is None)
-
- def test_checkPermission(self):
- from zope.security 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.assert_(p is permission)
- self.assert_(o is obj)
- self.assert_(s is queryInteraction() or s is interaction)
- return s is interaction
-
- setSecurityPolicy(PolicyStub)
- newInteraction()
- interaction = queryInteraction()
- self.assertEquals(checkPermission(permission, obj), True)
-
- def test_checkPublicPermission(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.assertEquals(checkPermission('zope.Test', obj), False)
- self.assertEquals(checkPermission(None, obj), True)
- self.assertEquals(checkPermission(CheckerPublic, obj), True)
-
- def test_system_user(self):
- from zope.security.management import system_user
- self.assertEquals(system_user.id,
- u'zope.security.management.system_user')
-
- self.assert_(system_user.title)
- for name in 'id', 'title', 'description':
- self.assert_(isinstance(getattr(system_user, name), unicode))
-
-def test_suite():
- loader = unittest.TestLoader()
- return loader.loadTestsFromTestCase(Test)
-
-if __name__=='__main__':
- unittest.TextTestRunner().run(test_suite())
diff --git a/src/zope/security/tests/test_permission.py b/src/zope/security/tests/test_permission.py
deleted file mode 100644
index 9d90f20..0000000
--- a/src/zope/security/tests/test_permission.py
+++ /dev/null
@@ -1,31 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 Zope Corporation 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
-
-$Id$
-"""
-import unittest
-from zope.testing.doctestunit import DocTestSuite
-from zope.component.testing import setUp, tearDown
-
-__docformat__ = "reStructuredText"
-
-def test_suite():
- return unittest.TestSuite([
- DocTestSuite('zope.security.permission',
- setUp=setUp, tearDown=tearDown),
- ])
-
-if __name__ == '__main__':
- unittest.main(defaultTest='test_suite')
diff --git a/src/zope/security/tests/test_proxy.py b/src/zope/security/tests/test_proxy.py
deleted file mode 100644
index b983ec7..0000000
--- a/src/zope/security/tests/test_proxy.py
+++ /dev/null
@@ -1,447 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation 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
-
-$Id$
-"""
-
-import unittest
-from zope.testing.doctest import DocTestSuite
-from zope.security.proxy import getChecker, ProxyFactory, removeSecurityProxy
-from zope.proxy import ProxyBase as proxy
-
-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):
- 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
- 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):
- 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):
- self.assert_(isinstance(self.p, proxy))
-
- def testStr(self):
- self.assertEqual(str(self.p), str(self.x))
-
- x = Something()
- c = Checker()
- c.ok = 0
- p = ProxyFactory(x, c)
- s = str(p)
- self.failUnless(s.startswith(
- "<security proxied %s.%s instance at"
- % (x.__class__.__module__, x.__class__.__name__)),
- s)
-
-
- def testRepr(self):
- self.assertEqual(repr(self.p), repr(self.x))
-
- x = Something()
- c = Checker()
- c.ok = 0
- p = ProxyFactory(x, c)
- s = repr(p)
- self.failUnless(s.startswith(
- "<security proxied %s.%s instance at"
- % (x.__class__.__module__, x.__class__.__name__)),
- s)
-
- def testGetAttrOK(self):
- self.assertEqual(removeSecurityProxy(self.p.foo), [1,2,3])
-
- def testGetAttrFail(self):
- self.assertRaises(RuntimeError, lambda: self.p.bar)
-
- def testSetAttrOK(self):
- self.p.foo = 42
- self.assertEqual(self.p.foo, 42)
-
- def testSetAttrFail(self):
- def doit(): self.p.bar = 42
- self.assertRaises(RuntimeError, doit)
-
- def testGetItemOK(self):
- self.assertEqual(self.p[0], 1)
-
- def testGetItemFail(self):
- self.shouldFail(lambda: self.p[10])
-
- def testSetItemOK(self):
- self.p[0] = 42
- self.assertEqual(self.p[0], 42)
-
- def testSetItemFail(self):
- def doit(): del self.p[0]
- self.shouldFail(doit)
-
- def testDelItemOK(self):
- self.p[0] = 42
- self.assertEqual(self.p[0], 42)
- del self.p[0]
- self.shouldFail(lambda: self.p[0])
-
- def testDelItemFail(self):
- def doit(): self.p[10] = 42
- self.shouldFail(doit)
-
- def testCallOK(self):
- self.assertEqual(self.p(None), 42)
-
- def testCallFail(self):
- self.shouldFail(self.p, None)
-
- def testRichCompareOK(self):
- self.failUnless(self.p == self.x)
-
-## def testRichCompareFail(self):
-## self.shouldFail(lambda: self.p == self.x)
-
- def testIterOK(self):
- self.assertEqual(removeSecurityProxy(iter(self.p)), self.x)
-
- def testIterFail(self):
- self.shouldFail(iter, self.p)
-
- def testNextOK(self):
- self.assertEqual(self.p.next(), 42)
-
- def testNextFail(self):
- self.shouldFail(self.p.next)
-
- def testCompareOK(self):
- self.assertEqual(cmp(self.p, self.x), 0)
-
-## def testCompareFail(self):
-## self.shouldFail(cmp, self.p, self.x)
-
- def testHashOK(self):
- self.assertEqual(hash(self.p), hash(self.x))
-
-## def testHashFail(self):
-## self.shouldFail(hash, self.p)
-
- def testNonzeroOK(self):
- self.assertEqual(not self.p, 0)
-
-## def testNonzeroFail(self):
-## self.shouldFail(lambda: not self.p)
-
- def testLenOK(self):
- self.assertEqual(len(self.p), 42)
-
- def testLenFail(self):
- self.shouldFail(len, self.p)
-
- def testSliceOK(self):
- self.assertEqual(removeSecurityProxy(self.p[:]), [42])
-
- def testSliceFail(self):
- self.shouldFail(lambda: self.p[:])
-
- def testSetSliceOK(self):
- self.p[:] = [42]
-
- def testSetSliceFail(self):
- def doit(): self.p[:] = [42]
- self.shouldFail(doit)
-
- def testContainsOK(self):
- self.failUnless(42 in self.p)
-
- def testContainsFail(self):
- self.shouldFail(lambda: 42 in self.p)
-
- def testGetObject(self):
- self.assertEqual(self.x, removeSecurityProxy(self.p))
-
- def testGetChecker(self):
- self.assertEqual(self.c, getChecker(self.p))
-
- def testProxiedClassicClassAsDictKey(self):
- class C(object):
- pass
- d = {C: C()}
- pC = ProxyFactory(C, self.c)
- self.assertEqual(d[pC], d[C])
-
- def testProxiedNewClassAsDictKey(self):
- class C(object):
- pass
- d = {C: C()}
- pC = ProxyFactory(C, self.c)
- self.assertEqual(d[pC], d[C])
-
- unops = [
- "-x", "+x", "abs(x)", "~x",
- "int(x)", "long(x)", "float(x)",
- ]
-
- def test_unops(self):
- # We want the starting value of the expressions to be a proxy,
- # but we don't want to create new proxies as a result of
- # evaluation, so we have to extend the list of types that
- # aren't proxied.
- self.c.unproxied_types = str, int, long, float
- for expr in self.unops:
- x = 1
- y = eval(expr)
- # Make sure 'x' is a proxy always:
- x = ProxyFactory(1, self.c)
- z = eval(expr)
- self.assertEqual(removeSecurityProxy(z), y,
- "x=%r; expr=%r" % (x, expr))
- self.shouldFail(lambda x: eval(expr), x)
-
- def test_odd_unops(self):
- # unops that don't return a proxy
- P = self.c.proxy
- for func in (
- hex, oct,
- # lambda x: not x,
- ):
- self.assertEqual(func(P(100)), func(100))
- self.shouldFail(func, P(100))
-
- binops = [
- "x+y", "x-y", "x*y", "x/y", "divmod(x, y)", "x**y", "x//y",
- "x<<y", "x>>y", "x&y", "x|y", "x^y",
- ]
-
- def test_binops(self):
- 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...
- 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.failUnless(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)
-
- def test_coerce(self):
- 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.failUnless(a is x and b is y)
-
- x = P(1)
- y = P(2.1)
- a, b = coerce(x, y)
- self.failUnless(removeSecurityProxy(a) == 1.0 and b is y)
- if fixed_coerce:
- self.failUnless(type(removeSecurityProxy(a)) is float and b is y)
-
- x = P(1.1)
- y = P(2)
- a, b = coerce(x, y)
- self.failUnless(a is x and removeSecurityProxy(b) == 2.0)
- if fixed_coerce:
- self.failUnless(a is x and type(removeSecurityProxy(b)) is float)
-
- x = P(1)
- y = 2
- a, b = coerce(x, y)
- self.failUnless(a is x and b is y)
-
- x = P(1)
- y = 2.1
- a, b = coerce(x, y)
- self.failUnless(type(removeSecurityProxy(a)) is float and b is y)
-
- x = P(1.1)
- y = 2
- a, b = coerce(x, y)
- self.failUnless(a is x and type(removeSecurityProxy(b)) is float)
-
- x = 1
- y = P(2)
- a, b = coerce(x, y)
- self.failUnless(a is x and b is y)
-
- x = 1.1
- y = P(2)
- a, b = coerce(x, y)
- self.failUnless(a is x and type(removeSecurityProxy(b)) is float)
-
- x = 1
- y = P(2.1)
- a, b = coerce(x, y)
- self.failUnless(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:
-
- >>> class Checker(object):
- ... def check(self, object, name):
- ... print 'check', name
- ... def check_getattr(self, object, name):
- ... print 'check_getattr', name
- ... def proxy(self, object):
- ... return 1
- >>> def f():
- ... pass
- >>> p = ProxyFactory(f, Checker())
- >>> p.__name__
- check_getattr __name__
- 1
- >>> p()
- check __call__
- 1
-
- But, if the checker has a __setitem__ method:
-
- >>> def __setitem__(self, object, name):
- ... print '__setitem__', name
- >>> Checker.__setitem__ = __setitem__
-
- It will be used rather than either check or check_getattr:
-
- >>> p.__name__
- __setitem__ __name__
- 1
- >>> p()
- __setitem__ __call__
- 1
-
- 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__
- __setitem__ __name__
- 2
- >>> p()
- __setitem__ __call__
- 2
-
- """
-
-
-
-def test_suite():
- suite = unittest.makeSuite(ProxyTests)
- suite.addTest(DocTestSuite())
- suite.addTest(DocTestSuite('zope.security.proxy'))
- return suite
-
-if __name__=='__main__':
- from unittest import main
- main(defaultTest='test_suite')
diff --git a/src/zope/security/tests/test_set_checkers.py b/src/zope/security/tests/test_set_checkers.py
deleted file mode 100644
index 0c28dec..0000000
--- a/src/zope/security/tests/test_set_checkers.py
+++ /dev/null
@@ -1,219 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation 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 checkers for standard types
-
-This is a test of the assertions made in
-zope.security.checkers._default_checkers.
-
-$Id$
-"""
-import unittest
-from zope.testing.doctestunit import DocTestSuite
-from zope.security.checker import ProxyFactory
-from zope.security.interfaces import ForbiddenAttribute
-import sets
-
-def check_forbidden_get(object, attr):
- try:
- return getattr(object, attr)
- except ForbiddenAttribute, e:
- return 'ForbiddenAttribute: %s' % e[0]
-
-def test_set():
- """Test that we can do everything we expect to be able to do
-
- with proxied sets.
-
- >>> 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.
-
- >>> bool(s)
- True
- >>> s.__class__ == set
- True
- """
-
-def setUpFrozenSet(test):
- test.globs['set'] = frozenset
-
-def setUpSet(test):
- test.globs['set'] = sets.Set
-
-def setUpImmutableSet(test):
- test.globs['set'] = sets.ImmutableSet
-
-def test_suite():
- return unittest.TestSuite((
- DocTestSuite(),
- DocTestSuite(setUp=setUpFrozenSet),
- DocTestSuite(setUp=setUpSet),
- DocTestSuite(setUp=setUpImmutableSet),
- ))
-
-if __name__ == '__main__':
- import unittest
- unittest.main()
diff --git a/src/zope/security/tests/test_simpleinteraction.py b/src/zope/security/tests/test_simpleinteraction.py
deleted file mode 100644
index b6a5bbb..0000000
--- a/src/zope/security/tests/test_simpleinteraction.py
+++ /dev/null
@@ -1,81 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation 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.
-
-$Id$
-"""
-import unittest
-
-from zope.interface.verify import verifyObject
-from zope.security.interfaces import IInteraction
-from zope.security.simplepolicies import ParanoidSecurityPolicy
-
-class RequestStub(object):
-
- def __init__(self, principal=None):
- self.principal = principal
- self.interaction = None
-
-
-class TestInteraction(unittest.TestCase):
-
- def test(self):
- interaction = ParanoidSecurityPolicy()
- verifyObject(IInteraction, interaction)
-
- def test_add(self):
- rq = RequestStub()
- interaction = ParanoidSecurityPolicy()
- interaction.add(rq)
- self.assert_(rq in interaction.participations)
- self.assert_(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):
- rq = RequestStub()
- interaction = ParanoidSecurityPolicy()
-
- self.assertRaises(ValueError, interaction.remove, rq)
-
- interaction.add(rq)
-
- interaction.remove(rq)
- self.assert_(rq not in interaction.participations)
- self.assert_(rq.interaction is None)
-
- def testCreateInteraction(self):
- i1 = ParanoidSecurityPolicy()
- verifyObject(IInteraction, i1)
- self.assertEquals(list(i1.participations), [])
-
- user = object()
- request = RequestStub(user)
- i2 = ParanoidSecurityPolicy(request)
- verifyObject(IInteraction, i2)
- self.assertEquals(list(i2.participations), [request])
-
-
-def test_suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(TestInteraction))
- return suite
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/src/zope/security/tests/test_standard_checkers.py b/src/zope/security/tests/test_standard_checkers.py
deleted file mode 100644
index 3c33948..0000000
--- a/src/zope/security/tests/test_standard_checkers.py
+++ /dev/null
@@ -1,498 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation 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 checkers for standard types
-
-This is a test of the assertions made in
-zope.security.checkers._default_checkers.
-
-$Id$
-"""
-from zope.security.checker import ProxyFactory, NamesChecker
-from zope.security.interfaces import ForbiddenAttribute
-
-
-def check_forbidden_get(object, attr):
- try:
- return getattr(object, attr)
- except ForbiddenAttribute, e:
- return 'ForbiddenAttribute: %s' % e[0]
-
-
-def check_forbidden_setitem(object, item, value):
- try:
- object[item] = value
- except ForbiddenAttribute, e:
- return 'ForbiddenAttribute: %s' % e[0]
-
-
-def check_forbidden_delitem(object, item):
- try:
- del object[item]
- except ForbiddenAttribute, e:
- return 'ForbiddenAttribute: %s' % e[0]
-
-
-def check_forbidden_call(callable, *args):
- try:
- return callable(*args)
- except ForbiddenAttribute, e:
- return 'ForbiddenAttribute: %s' % e[0]
-
-
-def test_dict():
- """Test that we can do everything we expect to be able to do
-
- with proxied dicts.
-
- >>> 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
- >>> list(d)
- ['a', 'b']
- >>> d.get('a')
- 1
- >>> int(d.has_key('a'))
- 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(`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)]
-
- >>> sorted(d.iterkeys())
- ['a', 'b']
- >>> sorted(d.itervalues())
- [1, 2]
- >>> sorted(d.iteritems())
- [('a', 1), ('b', 2)]
-
- Always available:
-
- >>> int(d < d)
- 0
- >>> int(d > d)
- 0
- >>> int(d <= d)
- 1
- >>> int(d >= d)
- 1
- >>> int(d == d)
- 1
- >>> int(d != d)
- 0
- >>> int(bool(d))
- 1
- >>> int(d.__class__ == dict)
- 1
-
- """
-
-def test_list():
- """Test that we can do everything we expect to be able to do
-
- with proxied lists.
-
- >>> 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]'
- >>> `l`
- '[1, 2]'
- >>> l + l
- [1, 2, 1, 2]
-
- Always available:
-
- >>> 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
-
-
- """
-
-def test_tuple():
- """Test that we can do everything we expect to be able to do
-
- with proxied lists.
-
- >>> 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)'
- >>> `l`
- '(1, 2)'
- >>> l + l
- (1, 2, 1, 2)
-
- Always available:
-
- >>> 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
-
- """
-
-def test_iter():
- """
- >>> 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]
- """
-
-def test_new_class():
- """
-
- >>> class C(object):
- ... x = 1
- >>> C = ProxyFactory(C)
- >>> check_forbidden_call(C)
- 'ForbiddenAttribute: __call__'
- >>> check_forbidden_get(C, '__dict__')
- 'ForbiddenAttribute: __dict__'
- >>> s = str(C)
- >>> s = `C`
- >>> int(C.__module__ == __name__)
- 1
- >>> len(C.__bases__)
- 1
- >>> len(C.__mro__)
- 2
-
- Always available:
-
- >>> int(C < C)
- 0
- >>> int(C > C)
- 0
- >>> int(C <= C)
- 1
- >>> int(C >= C)
- 1
- >>> int(C == C)
- 1
- >>> int(C != C)
- 0
- >>> int(bool(C))
- 1
- >>> int(C.__class__ == type)
- 1
-
- """
-
-def test_new_instance():
- """
-
- >>> 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:
-
- >>> int(c < c)
- 0
- >>> int(c > c)
- 0
- >>> int(c <= c)
- 1
- >>> int(c >= c)
- 1
- >>> int(c == c)
- 1
- >>> int(c != c)
- 0
- >>> int(bool(c))
- 1
- >>> int(c.__class__ == C)
- 1
-
- """
-
-def test_classic_class():
- """
-
- >>> class C:
- ... x = 1
- >>> C = ProxyFactory(C)
- >>> check_forbidden_call(C)
- 'ForbiddenAttribute: __call__'
- >>> check_forbidden_get(C, '__dict__')
- 'ForbiddenAttribute: __dict__'
- >>> s = str(C)
- >>> s = `C`
- >>> int(C.__module__ == __name__)
- 1
- >>> len(C.__bases__)
- 0
-
- Always available:
-
- >>> int(C < C)
- 0
- >>> int(C > C)
- 0
- >>> int(C <= C)
- 1
- >>> int(C >= C)
- 1
- >>> int(C == C)
- 1
- >>> int(C != C)
- 0
- >>> int(bool(C))
- 1
-
- """
-
-def test_classic_instance():
- """
-
- >>> 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:
-
- >>> int(c < c)
- 0
- >>> int(c > c)
- 0
- >>> int(c <= c)
- 1
- >>> int(c >= c)
- 1
- >>> int(c == c)
- 1
- >>> int(c != c)
- 0
- >>> int(bool(c))
- 1
- >>> int(c.__class__ == C)
- 1
-
- """
-
-def test_rocks():
- """
- >>> 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( 1l )) is long)
- 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( u'xxx' )) is unicode)
- 1
- >>> int(type(ProxyFactory( True )) is type(True))
- 1
-
- >>> 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
-
- >>> from pytz import UTC
- >>> int(type(ProxyFactory( UTC )) is type(UTC))
- 1
- """
-
-def test_iter_of_sequences():
- """
- >>> class X(object):
- ... d = 1, 2, 3
- ... def __getitem__(self, i):
- ... return self.d[i]
- ...
- >>> x = X()
-
- We can iterate over sequences
-
- >>> list(x)
- [1, 2, 3]
- >>> c = NamesChecker(['__getitem__'])
- >>> p = ProxyFactory(x, c)
-
- Even if they are proxied
-
- >>> list(p)
- [1, 2, 3]
-
- But if the class has an iter:
-
- >>> 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:
-
- >>> check_forbidden_call(list, p)
- 'ForbiddenAttribute: __iter__'
- """
-
-def test_interfaces_and_declarations():
- """Test that we can still use interfaces though proxies
-
- >>> import zope.interface
- >>> class I(zope.interface.Interface):
- ... pass
- >>> class IN(zope.interface.Interface):
- ... pass
- >>> class II(zope.interface.Interface):
- ... pass
- >>> class N(object):
- ... zope.interface.implements(I)
- ... zope.interface.classProvides(IN)
- >>> n = N()
- >>> zope.interface.directlyProvides(n, II)
- >>> from zope.security.checker import ProxyFactory
- >>> N = ProxyFactory(N)
- >>> n = ProxyFactory(n)
- >>> I.implementedBy(N)
- True
- >>> IN.providedBy(N)
- True
- >>> I.providedBy(n)
- True
- >>> II.providedBy(n)
- True
- """
-
-
-from zope.testing.doctestunit import DocTestSuite
-
-def test_suite():
- return DocTestSuite()
-
-if __name__ == '__main__':
- import unittest
- unittest.main()
diff --git a/src/zope/security/untrustedinterpreter.txt b/src/zope/security/untrustedinterpreter.txt
deleted file mode 100644
index ecbd17e..0000000
--- a/src/zope/security/untrustedinterpreter.txt
+++ /dev/null
@@ -1,220 +0,0 @@
-======================
-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.
diff --git a/src/zope/security/untrustedpython/__init__.py b/src/zope/security/untrustedpython/__init__.py
deleted file mode 100644
index 792d600..0000000
--- a/src/zope/security/untrustedpython/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-#
diff --git a/src/zope/security/untrustedpython/builtins.py b/src/zope/security/untrustedpython/builtins.py
deleted file mode 100644
index 9f47840..0000000
--- a/src/zope/security/untrustedpython/builtins.py
+++ /dev/null
@@ -1,126 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002 Zope Corporation 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
-#
-##############################################################################
-"""Protection of builtin objects.
-
-$Id$
-"""
-from zope.security.proxy import ProxyFactory
-import new
-
-def SafeBuiltins():
-
- builtins = {}
-
- from zope.security.checker import NamesChecker
- import __builtin__
-
- _builtinTypeChecker = NamesChecker(
- ['__str__', '__repr__', '__name__', '__module__',
- '__bases__', '__call__'])
-
- # It's better to say what is safe than it say what is not safe
- for name in [
-
- # Names of safe objects. See untrustedinterpreter.txt for a
- # definition of safe objects.
-
- 'ArithmeticError', 'AssertionError', 'AttributeError',
- 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError',
- 'Exception', 'FloatingPointError', 'IOError', 'ImportError',
- 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt',
- 'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented',
- 'NotImplementedError', 'OSError', 'OverflowError', 'OverflowWarning',
- 'ReferenceError', 'RuntimeError', 'RuntimeWarning', 'StandardError',
- 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError',
- 'SystemExit', 'TabError', 'TypeError', 'UnboundLocalError',
- 'UnicodeError', 'UserWarning', 'ValueError', 'Warning',
- 'ZeroDivisionError',
- '__debug__', '__name__', '__doc__', 'abs', 'apply', 'bool',
- 'buffer', 'callable', 'chr', 'classmethod', 'cmp', 'coerce',
- 'complex', 'copyright', 'credits', 'delattr',
- 'dict', 'divmod', 'filter', 'float', 'getattr',
- 'hasattr', 'hash', 'hex', 'id', 'int', 'isinstance',
- 'issubclass', 'iter', 'len', 'license', 'list',
- 'long', 'map', 'max', 'min', 'object', 'oct', 'ord', 'pow',
- 'property', 'quit', 'range', 'reduce', 'repr', 'round',
- 'setattr', 'slice', 'staticmethod', 'str', 'super', 'tuple',
- 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip',
- 'True', 'False',
-
- # TODO: dir segfaults with a seg fault due to a bas tuple
- # check in merge_class_dict in object.c. The assert macro
- # seems to be doing the wrong think. Basically, if an object
- # has bases, then bases is assumed to be a tuple.
- #dir,
- ]:
-
- try:
- value = getattr(__builtin__, name)
- except AttributeError:
- pass
- else:
- if isinstance(value, type):
- value = ProxyFactory(value, _builtinTypeChecker)
- else:
- value = ProxyFactory(value)
- builtins[name] = value
-
- from sys import modules
-
- def _imp(name, fromlist, prefix=''):
- module = modules.get(prefix+name)
- if module is not None:
- if fromlist or ('.' not in name):
- return module
- return modules[prefix+name.split('.')[0]]
-
- def __import__(name, globals=None, locals=None, fromlist=()):
- # Waaa, we have to emulate __import__'s weird semantics.
-
- if globals:
- __name__ = globals.get('__name__')
- if __name__:
- # Maybe do a relative import
- if '__path__' not in globals:
- # We have an ordinary module, not a package,
- # so remove last name segment:
- __name__ = '.'.join(__name__.split('.')[:-1])
- if __name__:
- module = _imp(name, fromlist, __name__+'.')
- if module is not None:
- return module
-
- module = _imp(name, fromlist)
- if module is not None:
- return module
-
- raise ImportError(name)
-
- builtins['__import__'] = ProxyFactory(__import__)
-
- return builtins
-
-class ImmutableModule(new.module):
- def __init__(self, name='__builtins__', **kw):
- new.module.__init__(self, name)
- self.__dict__.update(kw)
-
- def __setattr__(self, name, v):
- raise AttributeError(name)
-
- def __delattr__(self, name):
- raise AttributeError(name)
-
-
-SafeBuiltins = ImmutableModule(**SafeBuiltins())
diff --git a/src/zope/security/untrustedpython/builtins.txt b/src/zope/security/untrustedpython/builtins.txt
deleted file mode 100644
index f3c3071..0000000
--- a/src/zope/security/untrustedpython/builtins.txt
+++ /dev/null
@@ -1,114 +0,0 @@
-Safe Builtins
-=============
-
-When executing untrusted Python code, we need to make sure that we
-only give the code access to safe, basic or proxied objects. This
-included the builtin objects provided to Python code through a special
-__builtins__ module in globals. The `builtins` module provides a
-suitable module object:
-
- >>> from zope.security.untrustedpython.builtins import SafeBuiltins
- >>> d = {'__builtins__': SafeBuiltins}
- >>> exec 'x = str(1)' in d
- >>> d['x']
- '1'
-
-The object is immutable:
-
- >>> SafeBuiltins.foo = 1
- Traceback (most recent call last):
- ...
- AttributeError: foo
-
- >>> del SafeBuiltins['getattr']
- Traceback (most recent call last):
- ...
- TypeError: object does not support item deletion
-
-
-
- Exception raised:
- ...
- TypeError: object does not support item deletion
-
-(Note that you can mutate it through its `__dict__` attribute,
- however, when combined with the untrusted code compiler, getting the
- `__dict__` attribute will return a proxied object that will prevent
- mutation.)
-
-It contains items with keys that are all strings and values that are
-either proxied or are basic types:
-
- >>> from zope.security.proxy import Proxy
- >>> for key, value in SafeBuiltins.__dict__.items():
- ... if not isinstance(key, str):
- ... raise TypeError(key)
- ... if value is not None and not isinstance(value, (Proxy, int, str)):
- ... raise TypeError(value, key)
-
-It doesn't contain unsafe items, such as eval, globals, etc:
-
- >>> SafeBuiltins.eval
- Traceback (most recent call last):
- ...
- AttributeError: 'ImmutableModule' object has no attribute 'eval'
- >>> SafeBuiltins.globals
- Traceback (most recent call last):
- ...
- AttributeError: 'ImmutableModule' object has no attribute 'globals'
-
-The safe builtins also contains a custom __import__ function.
-
- >>> imp = SafeBuiltins.__import__
-
-As with regular import, it only returns the top-level package if no
-fromlist is specified:
-
- >>> import zope.security
- >>> imp('zope.security') == zope
- True
- >>> imp('zope.security', {}, {}, ['*']) == zope.security
- True
-
-Note that the values returned are proxied:
-
- >>> type(imp('zope.security')) is Proxy
- True
-
-This means that, having imported a module, you will only be able to
-access attributes for which you are authorized.
-
-Unlike regular __import__, you can nly import modules that have been
-previously imported. This is to prevent unauthorized execution of
-module-initialization code:
-
- >>> security = zope.security
- >>> import sys
- >>> del sys.modules['zope.security']
- >>> imp('zope.security')
- Traceback (most recent call last):
- ...
- ImportError: zope.security
-
- >>> sys.modules['zope.security'] = security
-
-Package-relative imports are supported (for now):
-
- >>> imp('security', {'__name__': 'zope', '__path__': []}) == security
- True
- >>> imp('security', {'__name__': 'zope.foo'}) == zope.security
- True
-
- >>> imp('security.untrustedpython', {'__name__': 'zope.foo'}) == security
- True
- >>> from zope.security import untrustedpython
- >>> imp('security.untrustedpython', {'__name__': 'zope.foo'}, {}, ['*']
- ... ) == untrustedpython
- True
-
-
-
-
-
-
-
diff --git a/src/zope/security/untrustedpython/interpreter.py b/src/zope/security/untrustedpython/interpreter.py
deleted file mode 100644
index c64c98c..0000000
--- a/src/zope/security/untrustedpython/interpreter.py
+++ /dev/null
@@ -1,78 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002 Zope Corporation 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
-#
-##############################################################################
-"""Restricted interpreter.
-
-TODO: This code needs a serious security review!!!
-
-$Id$
-"""
-from zope.security.untrustedpython.builtins import SafeBuiltins
-from zope.security.untrustedpython.rcompile import compile
-import warnings
-
-class RestrictedInterpreter(object):
-
- def __init__(self):
- warnings.warn("RestrictedInterpreter was deprecated 2004/7/27",
- DeprecationWarning, 2)
- self.globals = {}
- self.locals = {}
-
- def ri_exec(self, code):
- """Execute Python code in a restricted environment.
-
- The value of code can be either source or binary code."""
- if isinstance(code, basestring):
- code = compile(code, '<string>', 'exec')
- self.globals['__builtins__'] = SafeBuiltins
- exec code in self.globals, self.locals
-
-def exec_code(code, globals, locals=None):
- globals['__builtins__'] = SafeBuiltins
- exec code in globals, locals
-
-def exec_src(source, globals, locals=None):
- globals['__builtins__'] = SafeBuiltins
- code = compile(source, '<string>', 'exec')
- exec code in globals, locals
-
-
-class CompiledExpression(object):
- """A compiled expression
- """
-
- def __init__(self, source, filename='<string>'):
- self.source = source
- self.code = compile(source, filename, 'eval')
-
- def eval(self, globals, locals=None):
- globals['__builtins__'] = SafeBuiltins
- if locals is None:
- return eval(self.code, globals)
- else:
- return eval(self.code, globals)
-
-class CompiledProgram(object):
- """A compiled expression
- """
-
- def __init__(self, source, filename='<string>'):
- self.source = source
- self.code = compile(source, filename, 'exec')
-
- def exec_(self, globals, locals=None, output=None):
- globals['__builtins__'] = SafeBuiltins
- if output is not None:
- globals['untrusted_output'] = output
- exec self.code in globals, locals
diff --git a/src/zope/security/untrustedpython/interpreter.txt b/src/zope/security/untrustedpython/interpreter.txt
deleted file mode 100644
index dce15da..0000000
--- a/src/zope/security/untrustedpython/interpreter.txt
+++ /dev/null
@@ -1,112 +0,0 @@
-Untrusted Python interpreter
-============================
-
-The interpreter module provides very basic Python interpreter
-support. It combined untrusted code compilation with safe builtins
-and an exec-like API. The exec_src function can be used to execute
-Python source:
-
- >>> from zope.security.untrustedpython.interpreter import exec_src
- >>> d = {}
- >>> exec_src("x=1", d)
- >>> d['x']
- 1
-
- >>> exec_src("x=getattr", d)
-
-
-Note that the safe builtins dictionary is inserted into the
-dictionary:
-
- >>> from zope.security.untrustedpython.builtins import SafeBuiltins
- >>> d['__builtins__'] == SafeBuiltins
- True
-
-All of the non-basic items in the safe builtins are proxied:
-
- >>> exec_src('str=str', d)
- >>> from zope.security.proxy import Proxy
- >>> type(d['str']) is Proxy
- True
-
-Note that, while you can get to the safe `__builtins__`'s dictionary,
-you can't use the dictionary to mutate it:
-
- >>> from zope.security.interfaces import ForbiddenAttribute
-
- >>> try: exec_src('__builtins__.__dict__["x"] = 1', d)
- ... except ForbiddenAttribute: print 'Forbidden!'
- Forbidden!
-
- >>> try: exec_src('del __builtins__.__dict__["str"]', d)
- ... except ForbiddenAttribute: print 'Forbidden!'
- Forbidden!
-
- >>> try: exec_src('__builtins__.__dict__.update({"x": 1})', d)
- ... except ForbiddenAttribute: print 'Forbidden!'
- Forbidden!
-
-Because the untrusted code compiler is used, you can't use exec,
-raise, or try/except statements:
-
- >>> exec_src("exec 'x=1'", d)
- Traceback (most recent call last):
- ...
- SyntaxError: Line 1: exec statements are not supported
-
-Any attribute-access results will be proxied:
-
- >>> exec_src("data = {}\nupdate = data.update\nupdate({'x': 'y'})", d)
- >>> type(d['update']) is Proxy
- True
-
-In this case, we were able to get to and use the update method because
-the data dictionary itself was created by the untrusted code and was,
-thus, unproxied.
-
-You can compile code yourself and call exec_code instead:
-
- >>> from zope.security.untrustedpython.rcompile import compile
- >>> code = compile('x=2', '<mycode>', 'exec')
- >>> d = {}
- >>> from zope.security.untrustedpython.interpreter import exec_code
- >>> exec_code(code, d)
- >>> d['x']
- 2
-
-This is useful if you are going to be executing the same expression
-many times, as you can avoid the cost of repeated comilation.
-
-Compiled Programs
------------------
-
-A slightly higher-level interface is provided by compiled programs.
-These make it easier to safetly safe the results of compilation:
-
- >>> from zope.security.untrustedpython.interpreter import CompiledProgram
- >>> p = CompiledProgram('x=2')
- >>> d = {}
- >>> p.exec_(d)
- >>> d['x']
- 2
-
-When you execute a compiled program, you can supply an object with a
-write method to get print output:
-
- >>> p = CompiledProgram('print "Hello world!"')
- >>> import cStringIO
- >>> f = cStringIO.StringIO()
- >>> p.exec_({}, output=f)
- >>> f.getvalue()
- 'Hello world!\n'
-
-
-Compiled Expressions
---------------------
-
-You can also precompile expressions:
-
- >>> from zope.security.untrustedpython.interpreter import CompiledExpression
- >>> p = CompiledExpression('x*2')
- >>> p.eval({'x': 2})
- 4
diff --git a/src/zope/security/untrustedpython/rcompile.py b/src/zope/security/untrustedpython/rcompile.py
deleted file mode 100644
index 93452c8..0000000
--- a/src/zope/security/untrustedpython/rcompile.py
+++ /dev/null
@@ -1,97 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 Zope Corporation 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.
-#
-##############################################################################
-"""compile() equivalent that produces restricted code.
-
-Only 'eval' is supported at this time.
-
-$Id$
-"""
-
-import compiler.pycodegen
-
-import RestrictedPython.RCompile
-from RestrictedPython.SelectCompiler import ast, OP_ASSIGN, OP_DELETE, OP_APPLY
-
-def compile(text, filename, mode):
- if not isinstance(text, basestring):
- raise TypeError("Compiled source must be string")
- gen = RExpression(text, str(filename), mode)
- gen.compile()
- return gen.getCode()
-
-class RExpression(RestrictedPython.RCompile.RestrictedCompileMode):
-
- CodeGeneratorClass = compiler.pycodegen.ExpressionCodeGenerator
-
- def __init__(self, source, filename, mode = "eval"):
- self.mode = mode
- RestrictedPython.RCompile.RestrictedCompileMode.__init__(
- self, source, filename)
- self.rm = RestrictionMutator()
-
-
-# The security checks are performed by a set of six functions that
-# must be provided by the restricted environment.
-
-_getattr_name = ast.Name("getattr")
-
-
-class RestrictionMutator:
-
- def __init__(self):
- self.errors = []
- self.warnings = []
- self.used_names = {}
-
- def error(self, node, info):
- """Records a security error discovered during compilation."""
- lineno = getattr(node, 'lineno', None)
- if lineno is not None and lineno > 0:
- self.errors.append('Line %d: %s' % (lineno, info))
- else:
- self.errors.append(info)
-
- def visitGetattr(self, node, walker):
- """Converts attribute access to a function call.
-
- 'foo.bar' becomes 'getattr(foo, "bar")'.
-
- Also prevents augmented assignment of attributes, which would
- be difficult to support correctly.
- """
- node = walker.defaultVisitNode(node)
- return ast.CallFunc(_getattr_name,
- [node.expr, ast.Const(node.attrname)])
-
- def visitExec(self, node, walker):
- self.error(node, "exec statements are not supported")
-
- def visitPrint(self, node, walker):
- """Make sure prints always have a destination
-
- If we get a print without a destination, make the default destination
- untrusted_output.
- """
- node = walker.defaultVisitNode(node)
- if node.dest is None:
- node.dest = ast.Name('untrusted_output')
- return node
- visitPrintnl = visitPrint
-
- def visitRaise(self, node, walker):
- self.error(node, "raise statements are not supported")
-
- def visitTryExcept(self, node, walker):
- self.error(node, "try/except statements are not supported")
-
diff --git a/src/zope/security/untrustedpython/rcompile.txt b/src/zope/security/untrustedpython/rcompile.txt
deleted file mode 100644
index 919757e..0000000
--- a/src/zope/security/untrustedpython/rcompile.txt
+++ /dev/null
@@ -1,128 +0,0 @@
-==================================
-Support for Restricted Python Code
-==================================
-
-This package provides a way to compile
-untrusted Python code so that it can be executed safely.
-
-This form of restricted Python assumes that security proxies will be
-used to protect assets. Given this, the only thing that actually
-needs to be done differently by the generated code is to:
-
-- Ensure that all attribute lookups go through a safe version of the getattr()
- function that's been provided in the built-in functions used in the
- execution environment.
-
-- Prevent exec statements. (Later, we could possibly make exec safe.)
-
-- Print statements always go to an output that is provided as a
- global, rather than having an implicit sys.output.
-
-- Prevent try/except and raise statements. This is mainly because they
- don't work properly in the presense of security proxies. Try/except
- statements will be made to work in the future.
-
-No other special treatment is needed to support safe expression
-evaluation.
-
-The implementation makes use of the `RestrictedPython` package,
-originally written for Zope 2. There is a new AST re-writer in
-`zope.security.untrustedpython.rcompile` which performs the
-tree-transformation, and a top-level `compile()` function in
-`zope.security.untrustedpython.rcompile`; the later is what client
-applications are expected to use.
-
-The signature of the `compile()` function is very similar to that of
-Python's built-in `compile()` function::
-
- compile(source, filename, mode)
-
-Using it is equally simple::
-
- >>> from zope.security.untrustedpython.rcompile import compile
-
- >>> code = compile("21 * 2", "<string>", "eval")
- >>> eval(code)
- 42
-
-What's interesting about the restricted code is that all attribute
-lookups go through the `getattr()` function. This is generally
-provided as a built-in function in the restricted environment::
-
- >>> def mygetattr(object, name, default="Yahoo!"):
- ... marker = []
- ... print "Looking up", name
- ... if getattr(object, name, marker) is marker:
- ... return default
- ... else:
- ... return "Yeehaw!"
-
- >>> import __builtin__
- >>> builtins = __builtin__.__dict__.copy()
- >>> builtins["getattr"] = mygetattr
-
- >>> def reval(source):
- ... code = compile(source, "README.txt", "eval")
- ... globals = {"__builtins__": builtins}
- ... return eval(code, globals, {})
-
- >>> reval("(42).__class__")
- Looking up __class__
- 'Yeehaw!'
- >>> reval("(42).not_really_there")
- Looking up not_really_there
- 'Yahoo!'
- >>> reval("(42).foo.not_really_there")
- Looking up foo
- Looking up not_really_there
- 'Yahoo!'
-
-This allows a `getattr()` to be used that ensures the result of
-evaluation is a security proxy.
-
-To compile code with statements, use exec or single:
-
- >>> exec compile("x = 1", "<string>", "exec")
- >>> x
- 1
-
-Trying to compile exec, raise or try/except sattements gives
-syntax errors:
-
- >>> compile("exec 'x = 2'", "<string>", "exec")
- Traceback (most recent call last):
- ...
- SyntaxError: Line 1: exec statements are not supported
-
- >>> compile("raise KeyError('x')", "<string>", "exec")
- Traceback (most recent call last):
- ...
- SyntaxError: Line 1: raise statements are not supported
-
- >>> compile("try: pass\nexcept: pass", "<string>", "exec")
- Traceback (most recent call last):
- ...
- SyntaxError: Line 1: try/except statements are not supported
-
-Printing to an explicit writable is allowed:
-
- >>> import StringIO
- >>> f = StringIO.StringIO()
- >>> code = compile("print >> f, 'hi',\nprint >> f, 'world'", '', 'exec')
- >>> exec code in {'f': f}
- >>> f.getvalue()
- 'hi world\n'
-
-But if no output is specified, then output will be send to
-`untrusted_output`:
-
- >>> code = compile("print 'hi',\nprint 'world'", '', 'exec')
- >>> exec code in {}
- Traceback (most recent call last):
- ...
- NameError: name 'untrusted_output' is not defined
-
- >>> f = StringIO.StringIO()
- >>> exec code in {'untrusted_output': f}
-
-
diff --git a/src/zope/security/untrustedpython/tests.py b/src/zope/security/untrustedpython/tests.py
deleted file mode 100644
index 6557640..0000000
--- a/src/zope/security/untrustedpython/tests.py
+++ /dev/null
@@ -1,36 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.0 (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.
-#
-##############################################################################
-"""Untrusted python tests
-
-$Id$
-"""
-import unittest
-import re
-from zope.testing import doctestunit,renormalizing
-
-def test_suite():
- checker = renormalizing.RENormalizing([
- (re.compile(r"'ImmutableModule' object"),
- r'object'),
- ])
- return unittest.TestSuite((
- doctestunit.DocFileSuite('builtins.txt',
- 'rcompile.txt',
- 'interpreter.txt',checker=checker
- ),
- ))
-
-if __name__ == '__main__':
- unittest.main(defaultTest='test_suite')
-
diff --git a/src/zope/security/zcml.py b/src/zope/security/zcml.py
deleted file mode 100644
index 0c0c3c3..0000000
--- a/src/zope/security/zcml.py
+++ /dev/null
@@ -1,146 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 Zope Corporation 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.
-
-$Id$
-"""
-__docformat__ = 'restructuredtext'
-
-import zope.schema
-from zope.interface import Interface, implements
-from zope.schema.interfaces import IFromUnicode
-from zope.security.permission import checkPermission
-from zope.security.management import setSecurityPolicy
-from zope.configuration.fields import MessageID, GlobalObject
-
-class Permission(zope.schema.Id):
- r"""This field describes a permission.
-
- Let's look at an example:
-
- >>> 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:
-
- >>> field.fromUnicode(u'zope.foo')
- 'zope.foo'
- >>> field.fromUnicode(u'zope.ManageCode')
- 'zope.private'
-
- Now let's see whether validation works alright
-
- >>> field._validate('zope.ManageCode')
- >>> context._actions[0]['args']
- (None, 'zope.foo')
- >>> field._validate('3 foo')
- Traceback (most recent call last):
- ...
- InvalidId: 3 foo
-
- zope.Public is always valid
- >>> field._validate('zope.Public')
- """
- implements(IFromUnicode)
-
- 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 = zope.schema.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