SVN: ZODB/branches/3.4/src/ZEO/ - Fixed vulnerabilities in the ZEO network protocol

Andreas Jung <[email protected]>
Newsgroups gmane.comp.python.zope.zodb.cvs
Message-ID <20090806131651.C03579415B__22232.8807729811$1249564624$gmane$org@cvs.zope.org>
Log message for revision 102539:
  
        - Fixed vulnerabilities in the ZEO network protocol 
          affecting ZEO storage servers.
  

Changed:
  U   ZODB/branches/3.4/src/ZEO/StorageServer.py
  U   ZODB/branches/3.4/src/ZEO/auth/auth_digest.py
  U   ZODB/branches/3.4/src/ZEO/tests/auth_plaintext.py
  U   ZODB/branches/3.4/src/ZEO/zrpc/connection.py
  U   ZODB/branches/3.4/src/ZEO/zrpc/marshal.py

-=-
Modified: ZODB/branches/3.4/src/ZEO/StorageServer.py
===================================================================
--- ZODB/branches/3.4/src/ZEO/StorageServer.py	2009-08-06 13:15:38 UTC (rev 102538)
+++ ZODB/branches/3.4/src/ZEO/StorageServer.py	2009-08-06 13:16:51 UTC (rev 102539)
@@ -98,7 +98,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
@@ -350,6 +350,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.4/src/ZEO/auth/auth_digest.py
===================================================================
--- ZODB/branches/3.4/src/ZEO/auth/auth_digest.py	2009-08-06 13:15:38 UTC (rev 102538)
+++ ZODB/branches/3.4/src/ZEO/auth/auth_digest.py	2009-08-06 13:16:51 UTC (rev 102539)
@@ -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.4/src/ZEO/tests/auth_plaintext.py
===================================================================
--- ZODB/branches/3.4/src/ZEO/tests/auth_plaintext.py	2009-08-06 13:15:38 UTC (rev 102538)
+++ ZODB/branches/3.4/src/ZEO/tests/auth_plaintext.py	2009-08-06 13:16:51 UTC (rev 102539)
@@ -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.4/src/ZEO/zrpc/connection.py
===================================================================
--- ZODB/branches/3.4/src/ZEO/zrpc/connection.py	2009-08-06 13:15:38 UTC (rev 102538)
+++ ZODB/branches/3.4/src/ZEO/zrpc/connection.py	2009-08-06 13:16:51 UTC (rev 102539)
@@ -22,7 +22,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
@@ -724,6 +724,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.4/src/ZEO/zrpc/marshal.py
===================================================================
--- ZODB/branches/3.4/src/ZEO/zrpc/marshal.py	2009-08-06 13:15:38 UTC (rev 102538)
+++ ZODB/branches/3.4/src/ZEO/zrpc/marshal.py	2009-08-06 13:16:51 UTC (rev 102539)
@@ -53,6 +53,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__',)
 
@@ -77,3 +91,19 @@
         return r
 
     raise ZRPCError("Unsafe global: %s.%s" % (module, name))
+
+def server_find_global(module, name):
+    """Helper for message unpickler"""
+    try:
+        if module != 'ZopeUndo.Prefix':
+            raise ImportError
+        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))
+
+    return r
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.