SVN: ZODB/branches/3.8/ Bugs Fixed:

Jim Fulton <[email protected]>
Newsgroups gmane.comp.python.zope.zodb.cvs
Message-ID <20090813200730.9AE329417E__27760.1323825822$1250194065$gmane$org@cvs.zope.org>
Log message for revision 102741:
  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.
  

Changed:
  U   ZODB/branches/3.8/NEWS.txt
  U   ZODB/branches/3.8/setup.py
  U   ZODB/branches/3.8/src/ZEO/StorageServer.py
  U   ZODB/branches/3.8/src/ZEO/auth/auth_digest.py
  U   ZODB/branches/3.8/src/ZEO/tests/auth_plaintext.py
  U   ZODB/branches/3.8/src/ZEO/zrpc/connection.py
  U   ZODB/branches/3.8/src/ZEO/zrpc/marshal.py

-=-
Modified: ZODB/branches/3.8/NEWS.txt
===================================================================
--- ZODB/branches/3.8/NEWS.txt	2009-08-13 20:05:59 UTC (rev 102740)
+++ ZODB/branches/3.8/NEWS.txt	2009-08-13 20:07:30 UTC (rev 102741)
@@ -9,6 +9,23 @@
 - Fixed a pack test that was not compatible with storages that always
   return an object count of 0.
 
+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
 =======================
 

Modified: ZODB/branches/3.8/setup.py
===================================================================
--- ZODB/branches/3.8/setup.py	2009-08-13 20:05:59 UTC (rev 102740)
+++ ZODB/branches/3.8/setup.py	2009-08-13 20:07:30 UTC (rev 102741)
@@ -20,7 +20,7 @@
 interface, rich transaction support, and undo.
 """
 
-VERSION = "3.8.2dev"
+VERSION = "3.8.3dev"
 
 # The (non-obvious!) choices for the Trove Development Status line:
 # Development Status :: 5 - Production/Stable

Modified: ZODB/branches/3.8/src/ZEO/StorageServer.py
===================================================================
--- ZODB/branches/3.8/src/ZEO/StorageServer.py	2009-08-13 20:05:59 UTC (rev 102740)
+++ ZODB/branches/3.8/src/ZEO/StorageServer.py	2009-08-13 20:07:30 UTC (rev 102741)
@@ -111,7 +111,7 @@
         for func in self.extensions:
             self._extensions[func.func_name] = None
 
-    def finish_auth(self, authenticated):
+    def _finish_auth(self, authenticated):
         if not self.auth_realm:
             return 1
         self.authenticated = authenticated
@@ -421,6 +421,7 @@
 
     def new_oids(self, n=100):
         """Return a sequence of n new oids, where n defaults to 100"""
+        n = min(n, 100)
         if self.read_only:
             raise ReadOnlyError()
         if n <= 0:

Modified: ZODB/branches/3.8/src/ZEO/auth/auth_digest.py
===================================================================
--- ZODB/branches/3.8/src/ZEO/auth/auth_digest.py	2009-08-13 20:05:59 UTC (rev 102740)
+++ ZODB/branches/3.8/src/ZEO/auth/auth_digest.py	2009-08-13 20:07:30 UTC (rev 102741)
@@ -121,7 +121,7 @@
         check = hexdigest("%s:%s" % (h_up, challenge))
         if check == response:
             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]
 

Modified: ZODB/branches/3.8/src/ZEO/tests/auth_plaintext.py
===================================================================
--- ZODB/branches/3.8/src/ZEO/tests/auth_plaintext.py	2009-08-13 20:05:59 UTC (rev 102740)
+++ ZODB/branches/3.8/src/ZEO/tests/auth_plaintext.py	2009-08-13 20:07:30 UTC (rev 102741)
@@ -41,7 +41,7 @@
             self.connection.setSessionKey(session_key(username,
                                                       self.database.realm,
                                                       password))
-        return self.finish_auth(dbpw == password_dig)
+        return self._finish_auth(dbpw == password_dig)
 
 class PlaintextClient(Client):
     extensions = ["auth"]

Modified: ZODB/branches/3.8/src/ZEO/zrpc/connection.py
===================================================================
--- ZODB/branches/3.8/src/ZEO/zrpc/connection.py	2009-08-13 20:05:59 UTC (rev 102740)
+++ ZODB/branches/3.8/src/ZEO/zrpc/connection.py	2009-08-13 20:07:30 UTC (rev 102741)
@@ -24,7 +24,7 @@
 import ThreadedAsync
 from ZEO.zrpc import smac
 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.log import short_repr, log
 from ZODB.loglevels import BLATHER, TRACE
@@ -883,6 +883,7 @@
     def __init__(self, sock, addr, obj, mgr):
         self.mgr = mgr
         self.__super_init(sock, addr, obj, 'S')
+        self.marshal = ServerMarshaller()
         self.obj.notifyConnected(self)
 
     def handshake(self):

Modified: ZODB/branches/3.8/src/ZEO/zrpc/marshal.py
===================================================================
--- ZODB/branches/3.8/src/ZEO/zrpc/marshal.py	2009-08-13 20:05:59 UTC (rev 102740)
+++ ZODB/branches/3.8/src/ZEO/zrpc/marshal.py	2009-08-13 20:07:30 UTC (rev 102741)
@@ -52,6 +52,20 @@
                 level=logging.ERROR)
             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()
 _silly = ('__doc__',)
 
@@ -78,3 +92,21 @@
         return r
 
     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))
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.