Commit 74888d16 authored by Jim Fulton's avatar Jim Fulton

Bugs Fixed:

- Fixed vulnerabilities in the ZEO network protocol that allow:

CVE-2009-0668 Arbitrary Python code execution in ZODB ZEO storage servers
  CVE-2009-0669 Authentication bypass in ZODB ZEO storage servers

- Limit the number of object ids that can be allocated at once to
  avoid running out of memory.
parent 828f8c59
Whats new in ZODB 3.8.2
=======================
Bugs Fixed:
- Fixed vulnerabilities in the ZEO network protocol that allow:
- CVE-2009-0668 Arbitrary Python code execution in ZODB ZEO storage servers
- CVE-2009-0669 Authentication bypass in ZODB ZEO storage servers
The vulnerabilities only apply if you are using ZEO to share a
database among multiple applications or application instances and if
untrusted clients are able to connect to your ZEO servers.
- Limit the number of object ids that can be allocated at once to
avoid running out of memory.
Whats new in ZODB 3.8.1 Whats new in ZODB 3.8.1
======================= =======================
......
...@@ -20,7 +20,7 @@ to application logic. ZODB includes features such as a plugable storage ...@@ -20,7 +20,7 @@ to application logic. ZODB includes features such as a plugable storage
interface, rich transaction support, and undo. interface, rich transaction support, and undo.
""" """
VERSION = "3.8.1" VERSION = "3.8.2"
# The (non-obvious!) choices for the Trove Development Status line: # The (non-obvious!) choices for the Trove Development Status line:
# Development Status :: 5 - Production/Stable # Development Status :: 5 - Production/Stable
......
...@@ -111,7 +111,7 @@ class ZEOStorage: ...@@ -111,7 +111,7 @@ class ZEOStorage:
for func in self.extensions: for func in self.extensions:
self._extensions[func.func_name] = None self._extensions[func.func_name] = None
def finish_auth(self, authenticated): def _finish_auth(self, authenticated):
if not self.auth_realm: if not self.auth_realm:
return 1 return 1
self.authenticated = authenticated self.authenticated = authenticated
...@@ -421,6 +421,7 @@ class ZEOStorage: ...@@ -421,6 +421,7 @@ class ZEOStorage:
def new_oids(self, n=100): def new_oids(self, n=100):
"""Return a sequence of n new oids, where n defaults to 100""" """Return a sequence of n new oids, where n defaults to 100"""
n = min(n, 100)
if self.read_only: if self.read_only:
raise ReadOnlyError() raise ReadOnlyError()
if n <= 0: if n <= 0:
......
...@@ -121,7 +121,7 @@ class StorageClass(ZEOStorage): ...@@ -121,7 +121,7 @@ class StorageClass(ZEOStorage):
check = hexdigest("%s:%s" % (h_up, challenge)) check = hexdigest("%s:%s" % (h_up, challenge))
if check == response: if check == response:
self.connection.setSessionKey(session_key(h_up, self._key_nonce)) self.connection.setSessionKey(session_key(h_up, self._key_nonce))
return self.finish_auth(check == response) return self._finish_auth(check == response)
extensions = [auth_get_challenge, auth_response] extensions = [auth_get_challenge, auth_response]
......
...@@ -41,7 +41,7 @@ class StorageClass(ZEOStorage): ...@@ -41,7 +41,7 @@ class StorageClass(ZEOStorage):
self.connection.setSessionKey(session_key(username, self.connection.setSessionKey(session_key(username,
self.database.realm, self.database.realm,
password)) password))
return self.finish_auth(dbpw == password_dig) return self._finish_auth(dbpw == password_dig)
class PlaintextClient(Client): class PlaintextClient(Client):
extensions = ["auth"] extensions = ["auth"]
......
...@@ -24,7 +24,7 @@ import traceback, time ...@@ -24,7 +24,7 @@ import traceback, time
import ThreadedAsync import ThreadedAsync
from ZEO.zrpc import smac from ZEO.zrpc import smac
from ZEO.zrpc.error import ZRPCError, DisconnectedError from ZEO.zrpc.error import ZRPCError, DisconnectedError
from ZEO.zrpc.marshal import Marshaller from ZEO.zrpc.marshal import Marshaller, ServerMarshaller
from ZEO.zrpc.trigger import trigger from ZEO.zrpc.trigger import trigger
from ZEO.zrpc.log import short_repr, log from ZEO.zrpc.log import short_repr, log
from ZODB.loglevels import BLATHER, TRACE from ZODB.loglevels import BLATHER, TRACE
...@@ -883,6 +883,7 @@ class ManagedServerConnection(Connection): ...@@ -883,6 +883,7 @@ class ManagedServerConnection(Connection):
def __init__(self, sock, addr, obj, mgr): def __init__(self, sock, addr, obj, mgr):
self.mgr = mgr self.mgr = mgr
self.__super_init(sock, addr, obj, 'S') self.__super_init(sock, addr, obj, 'S')
self.marshal = ServerMarshaller()
self.obj.notifyConnected(self) self.obj.notifyConnected(self)
def handshake(self): def handshake(self):
......
...@@ -52,6 +52,20 @@ class Marshaller: ...@@ -52,6 +52,20 @@ class Marshaller:
level=logging.ERROR) level=logging.ERROR)
raise raise
class ServerMarshaller(Marshaller):
def decode(self, msg):
"""Decodes msg and returns its parts"""
unpickler = cPickle.Unpickler(StringIO(msg))
unpickler.find_global = server_find_global
try:
return unpickler.load() # msgid, flags, name, args
except:
log("can't decode message: %s" % short_repr(msg),
level=logging.ERROR)
raise
_globals = globals() _globals = globals()
_silly = ('__doc__',) _silly = ('__doc__',)
...@@ -78,3 +92,21 @@ def find_global(module, name): ...@@ -78,3 +92,21 @@ def find_global(module, name):
return r return r
raise ZRPCError("Unsafe global: %s.%s" % (module, name)) raise ZRPCError("Unsafe global: %s.%s" % (module, name))
def server_find_global(module, name):
"""Helper for message unpickler"""
try:
m = __import__(module, _globals, _globals, _silly)
except ImportError, msg:
raise ZRPCError("import error %s: %s" % (module, msg))
try:
r = getattr(m, name)
except AttributeError:
raise ZRPCError("module %s has no global %s" % (module, name))
safe = getattr(r, '__no_side_effects__', 0)
if safe:
return r
raise ZRPCError("Unsafe global: %s.%s" % (module, name))
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment