summaryrefslogtreecommitdiff
path: root/src/zope/security
diff options
context:
space:
mode:
authorStephan Richter <stephan.richter@gmail.com>2013-03-11 00:26:51 -0400
committerStephan Richter <stephan.richter@gmail.com>2013-03-11 00:26:51 -0400
commit53db18f89778d18cae8ad9e0581eb5f4e059a3f1 (patch)
treeb9830f25fd44d5c9cf8791957938e9513ba24c1a /src/zope/security
parent8cce64bbef274d776ac4856843ebe25b7d9cb51f (diff)
downloadzope-security-53db18f89778d18cae8ad9e0581eb5f4e059a3f1.tar.gz
Actually made the security proxy secure by not allowing access to
_wrapped and _checker.
Diffstat (limited to 'src/zope/security')
-rw-r--r--src/zope/security/proxy.py31
-rw-r--r--src/zope/security/tests/test_proxy.py14
2 files changed, 30 insertions, 15 deletions
diff --git a/src/zope/security/proxy.py b/src/zope/security/proxy.py
index 8291045..c393bc7 100644
--- a/src/zope/security/proxy.py
+++ b/src/zope/security/proxy.py
@@ -13,8 +13,6 @@
##############################################################################
"""Helper functions for Proxies.
"""
-__docformat__ = 'restructuredtext'
-
import functools
import sys
@@ -22,6 +20,8 @@ from zope.proxy import PyProxyBase
from zope.security._compat import PYPY
from zope.security.interfaces import ForbiddenAttribute
+# Never expose this attribute in an utrusted environment.
+_secret = str(hash(object()))
def _check_name(meth):
name = meth.__name__
@@ -74,11 +74,14 @@ class ProxyPy(PyProxyBase):
# Attribute protocol
def __getattribute__(self, name):
+ # Explicitely disallow _wrapped and _checker to be accessed.
+ if name in ('_wrapped', '_checker'):
+ raise AttributeError(name)
wrapped = super(PyProxyBase, self).__getattribute__('_wrapped')
- checker = super(PyProxyBase, self).__getattribute__('_checker')
- if name == '_wrapped':
+ if name == '_wrapped'+_secret:
return wrapped
- if name == '_checker':
+ checker = super(PyProxyBase, self).__getattribute__('_checker')
+ if name == '_checker'+_secret:
return checker
if name not in ['__cmp__', '__hash__', '__bool__', '__nonzero__',
'__lt__', '__le__', '__eq__', '__ne__', '__ge__',
@@ -90,7 +93,7 @@ class ProxyPy(PyProxyBase):
wrapped = super(PyProxyBase, self).__getattribute__('_wrapped')
checker = super(PyProxyBase, self).__getattribute__('_checker')
checker.check_getattr(wrapped, name)
- return checker.proxy(getattr(self._wrapped, name))
+ return checker.proxy(getattr(wrapped, name))
def __setattr__(self, name, value):
if name in ('_wrapped', '_checker'):
@@ -98,7 +101,7 @@ class ProxyPy(PyProxyBase):
wrapped = super(PyProxyBase, self).__getattribute__('_wrapped')
checker = super(PyProxyBase, self).__getattribute__('_checker')
checker.check_setattr(wrapped, name)
- setattr(self._wrapped, name, value)
+ setattr(wrapped, name, value)
def __delattr__(self, name):
if name in ('_wrapped', '_checker'):
@@ -106,7 +109,7 @@ class ProxyPy(PyProxyBase):
wrapped = super(PyProxyBase, self).__getattribute__('_wrapped')
checker = super(PyProxyBase, self).__getattribute__('_checker')
checker.check_setattr(wrapped, name)
- delattr(self._wrapped, name)
+ delattr(wrapped, name)
@_check_name
def __getslice__(self, start, end):
@@ -169,7 +172,11 @@ class ProxyPy(PyProxyBase):
wrapped = super(PyProxyBase, self).__getattribute__('_wrapped')
checker = super(PyProxyBase, self).__getattribute__('_checker')
checker.check_getattr(wrapped, '__coerce__')
- return PyProxyBase.__coerce__(self, other)
+ # Re-implement __coerce__(), so we do not depend on self._wrapped
+ left, right = coerce(wrapped, other)
+ if left == wrapped and type(left) is type(wrapped):
+ left = self
+ return left, right
def __str__(self):
try:
@@ -274,12 +281,10 @@ for name in ['__iadd__',
setattr(ProxyPy, name, _check_name_inplace(meth))
def getCheckerPy(proxy):
- return proxy._checker
+ return getattr(proxy, '_checker'+_secret)
def getObjectPy(proxy):
- # Aem, if this works, how is the Python implementation providing any
- # security?
- return proxy._wrapped
+ return getattr(proxy, '_wrapped'+_secret)
try:
from zope.security._proxy import _Proxy
diff --git a/src/zope/security/tests/test_proxy.py b/src/zope/security/tests/test_proxy.py
index 7c15d52..ce7a046 100644
--- a/src/zope/security/tests/test_proxy.py
+++ b/src/zope/security/tests/test_proxy.py
@@ -1327,13 +1327,23 @@ class ProxyPyTests(unittest.TestCase, ProxyTestBase):
from zope.security.proxy import ProxyPy
return ProxyPy
+ def test_wrapper_checker_unaccessible(self):
+ from zope.security.proxy import _secret
+ # Can't access '_wrapped' / '_checker' in C version
+ target = object()
+ checker = object()
+ proxy = self._makeOne(target, checker)
+ self.assertRaises(AttributeError, getattr, proxy, '_wrapped')
+ self.assertRaises(AttributeError, getattr, proxy, '_checker')
+
def test_ctor_w_checker(self):
+ from zope.security.proxy import _secret
# Can't access '_wrapped' / '_checker' in C version
target = object()
checker = object()
proxy = self._makeOne(target, checker)
- self.assertTrue(proxy._wrapped is target)
- self.assertTrue(proxy._checker is checker)
+ self.assertTrue(getattr(proxy, '_wrapped'+_secret) is target)
+ self.assertTrue(getattr(proxy, '_checker'+_secret) is checker)
def test___delattr___w__wrapped(self):
target = object()