[Zope3-checkins] CVS: Zope3/src/zope/security - builtins.py:1.1 context.py:1.1 interpreter.py:1.1 management.py:1.1 manager.py:1.1 simplepolicies.py:1.1 checker.py:1.3 restrictedbuiltins.py:NONE restrictedinterpreter.py:NONE securitycontext.py:NONE securitymanagement.py:NONE securitymanager.py:NONE simplesecuritypolicies.py:NONE

Jim Fulton jim@zope.com
Mon, 30 Dec 2002 22:35:45 -0500


Update of /cvs-repository/Zope3/src/zope/security
In directory cvs.zope.org:/tmp/cvs-serv32330/src/zope/security

Modified Files:
	checker.py 
Added Files:
	builtins.py context.py interpreter.py management.py manager.py 
	simplepolicies.py 
Removed Files:
	restrictedbuiltins.py restrictedinterpreter.py 
	securitycontext.py securitymanagement.py securitymanager.py 
	simplesecuritypolicies.py 
Log Message:
More renaming.


=== Added File Zope3/src/zope/security/builtins.py ===
##############################################################################
#
# Copyright (c) 2002 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
#
##############################################################################
"""

Revision information:
$Id: builtins.py,v 1.1 2002/12/31 03:35:13 jim Exp $
"""
import sys

def RestrictedBuiltins():

    from zope.security.proxy import ProxyFactory
    from zope.security.checker import NamesChecker

    # It's better to say what is safe than it say what is not safe
    _safe = [
        '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__', '__doc__', '__name__', 'abs', 'apply', 'buffer',
        'callable', 'chr', 'classmethod', 'cmp', 'coerce', 'compile',
        'complex', 'copyright', 'credits', 'delattr', 'dict',
        'divmod', 'eval', 'filter', 'float', 'getattr', 'globals',
        'hasattr', 'hash', 'hex', 'id', 'int', 'isinstance',
        'issubclass', 'iter', 'len', 'license', 'list', 'locals',
        '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',
        ]

    # XXX 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.

    # Anything that accesses an external file is a no no:
    # 'open', 'execfile', 'file'

    # We dont want restricted code to call exit: 'SystemExit', 'exit'

    # Other no nos:
    #    help prints
    #    input does I/O
    #    raw_input does I/O
    #    intern's effect is too global
    #    reload does import, XXX doesn't it use __import__?

    _builtinTypeChecker = NamesChecker(
        ['__str__', '__repr__', '__name__', '__module__',
         '__bases__', '__call__'])

    import __builtin__

    builtins = {}
    for name in _safe:
        value = getattr(__builtin__, name)
        if isinstance(value, type):
            value = ProxyFactory(value, _builtinTypeChecker)
        else:
            value = ProxyFactory(value)
        builtins[name] = value

    def __import__(name, globals=None, locals=None, fromlist=()):
        # Waaa, we have to emulate __import__'s weird semantics.
        try:
            module = sys.modules[name]
            if fromlist:
                return module

            l = name.find('.')
            if l < 0:
                return module

            return sys.modules[name[:l]]

        except KeyError:
            raise ImportError(name)

    builtins['__import__'] = ProxyFactory(__import__)

    return builtins

RestrictedBuiltins = RestrictedBuiltins()


=== Added File Zope3/src/zope/security/context.py ===
##############################################################################
#
# 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.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.
#
##############################################################################
""" Default ISecurityContext impl """

from zope.security.interfaces import ISecurityContext

class SecurityContext:
    """
        Capture transient request-specific security information.

        Attribute( 'stack'
                , 'A stack of elements, each either be an ExecutableObject'
                'or a tuple consisting of an ExecutableObject and a'
                'custom SecurityPolicy.'
                )

        Attribute( 'user'
                , 'The AUTHENTICATED_USER for the request.'
                )
    """

    def __init__( self, user ):

        self.stack       = []
        self.user        = user
        self.objectCache = {}


=== Added File Zope3/src/zope/security/interpreter.py ===
##############################################################################
#
# Copyright (c) 2002 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
#
##############################################################################
"""

Revision information:
$Id: interpreter.py,v 1.1 2002/12/31 03:35:13 jim Exp $
"""

import sys

from zope.security.proxy import ProxyFactory
from zope.security.builtins import RestrictedBuiltins

class RestrictedInterpreter:

    def __init__(self):
        self.globals = {'__builtins__' : RestrictedBuiltins}

    def ri_exec(self, code):
        # what is the type of code?
        exec code in self.globals


=== Added File Zope3/src/zope/security/management.py ===
##############################################################################
#
# 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.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.
#
##############################################################################
""" Default ISecurityManagement implementation """

system_user = object() # Special system user that has all permissions


from zope.security.interfaces import ISecurityManagement, ISecurityManagementSetup
from zope.security.manager import SecurityManager
from zope.security.manager import setSecurityPolicy as _setSecurityPolicy
from zope.security.context import SecurityContext

__implements__ = ( ISecurityManagement, ISecurityManagementSetup )

try:
    import thread
except:
    get_ident=lambda: 0
else:
    get_ident=thread.get_ident

_managers={}

from zope.testing.cleanup import addCleanUp
addCleanUp(_managers.clear)


#
#   ISecurityManagementSetup implementation
#
def newSecurityManager( user ):
    """
        Install a new SecurityManager, using user.  Return the
        old SecurityManager, if any, or None.
    """
    return replaceSecurityManager( SecurityManager( SecurityContext( user ) ) )

def replaceSecurityManager( old_manager ):
    """
        Replace the SecurityManager with 'old_manager', which
        must implement ISecurityManager.
    """
    thread_id = get_ident()
    old = _managers.get( thread_id, None )
    _managers[ thread_id ] = old_manager
    return old

def noSecurityManager():
    """
        Clear any existing SecurityManager.
    """
    try:
        del _managers[ get_ident() ]
    except KeyError:
        pass

#
#   ISecurityManagement implementation
#
def getSecurityManager():
    """
        Get a SecurityManager (create if needed).
    """
    thread_id = get_ident()
    manager=_managers.get( thread_id, None )

    if manager is None:
        newSecurityManager( None )
        manager=_managers.get( thread_id, None )

    return manager

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.
    """
    return _setSecurityPolicy( aSecurityPolicy )


=== Added File Zope3/src/zope/security/manager.py ===
##############################################################################
#
# 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.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.
#
##############################################################################
""" Default ISecurityManager implementation """

import os
from zope.security.simplepolicies import ParanoidSecurityPolicy

MAX_STACK_SIZE = 100

_defaultPolicy = ParanoidSecurityPolicy()

def _clear():
    global _defaultPolicy
    _defaultPolicy = ParanoidSecurityPolicy()

from zope.testing.cleanup import addCleanUp
addCleanUp(_clear)


def setSecurityPolicy( aSecurityPolicy ):
    """
        Set the system default security policy.

        This method should only be caused by system startup code. It should
        never, for example, be called during a web request.
    """
    global _defaultPolicy

    last, _defaultPolicy = _defaultPolicy, aSecurityPolicy

    return last

from zope.security.interfaces import ISecurityManager

class SecurityManager:
    """
        A security manager provides methods for checking access and managing
        executable context and policies.
    """
    __implements__ = ISecurityManager

    def __init__( self, context ):
        self._context = context
        self._policy = None

    def _getPolicy( self ):
        """
            Find current policy, or default.
        """
        policy = self._policy
        if policy is None:
            policy = _defaultPolicy
        return policy

    #
    #   ISecurityManager implementation
    #
    def getPrincipal( self ):
        """
            Return the authenticated user.

            This is equivalent to something like::

            REQUEST['AUTHENTICATED_USER']

            but is a bit cleaner, especially if 'REQUEST' isn't handy.
        """
        return self._context.user

    def checkPermission( self, permission, object ):
        """
            Check whether the security context allows the given
            permission on the given object. Return a boolean value.

            Arguments:

            permission -- A permission name

            object -- The object being accessed according to the permission
        """
        return self._getPolicy().checkPermission( permission, object
                                              , self._context )

    def pushExecutable( self, anExecutableObject ):
        """
            Push an ExecutableObject onto the manager's stack, and
            activate its custom security policy, if any.
        """
        stack=self._context.stack

        if len( stack ) >= MAX_STACK_SIZE:
            raise SystemError, 'Excessive recursion'

        stack.append( anExecutableObject )
        p = getattr( anExecutableObject, '_customSecurityPolicy', None )

        if p is not None:
            p = p()

        self._policy = p

    def popExecutable( self, anExecutableObject ):
        """
            Pop the topmost ExecutableObject from the stack, deactivating
            any custom security policy it might have installed.
        """
        stack=self._context.stack

        if not stack:
            return

        top = stack[-1]

        if top is anExecutableObject:
            del stack[-1]
        else:
            indexes = range(len(stack))
            indexes.reverse()
            for i in indexes:
                top=stack[i]
                if top is anExecutableObject:
                    del stack[i:]
                    break
            else:
                return

        if stack:

            top = stack[-1]
            p = getattr( top, '_customSecurityPolicy', None )

            if p is not None:
                p=p()
            self._policy=p

        else:
            self._policy=None

    def calledByExecutable( self ):
        """
            Return a boolean indicating whether the current request has
            invoked any IExecutableObjects.

            This can be used to determine if an object was called
            (more or less) directly from a URL, or if it was called by
            through-the-web provided code.
        """
        return len( self._context.stack )


=== Added File Zope3/src/zope/security/simplepolicies.py ===
##############################################################################
#
# 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.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.
#
##############################################################################
""" Simple ISecurityPolicy implementations."""

from zope.security.interfaces import ISecurityPolicy
from zope.exceptions import Unauthorized
from zope.security.management import system_user

class ParanoidSecurityPolicy:
    """
        Deny all access.
    """
    __implements__ = ISecurityPolicy

    def checkPermission( sel, permission, object, context ):
        if (context.user is system_user   # no user
            and not context.stack  # no untrusted code
            ):
            return 1 # Nobody not to trust!

        return 0

class PermissiveSecurityPolicy:
    """
        Allow all access
    """
    __implements__ = ISecurityPolicy

    def checkPermission( self, permission, object, context ):
        return 1


=== Zope3/src/zope/security/checker.py 1.2 => 1.3 ===
--- Zope3/src/zope/security/checker.py:1.2	Wed Dec 25 09:15:21 2002
+++ Zope3/src/zope/security/checker.py	Mon Dec 30 22:35:13 2002
@@ -5,7 +5,7 @@
 from zope.interface import Interface
 from zope.security._proxy import _Proxy as Proxy
 from zope.security.interfaces import ISecurityProxyFactory
-from zope.security.securitymanagement import getSecurityManager
+from zope.security.management import getSecurityManager
 import sys, os, types
 import datetime
 

=== Removed File Zope3/src/zope/security/restrictedbuiltins.py ===

=== Removed File Zope3/src/zope/security/restrictedinterpreter.py ===

=== Removed File Zope3/src/zope/security/securitycontext.py ===

=== Removed File Zope3/src/zope/security/securitymanagement.py ===

=== Removed File Zope3/src/zope/security/securitymanager.py ===

=== Removed File Zope3/src/zope/security/simplesecuritypolicies.py ===