[Zope-Checkins] CVS: ZODB3/ZEO/zrpc - smac.py:1.38.6.3

Jeremy Hylton jeremy at zope.com
Fri Sep 19 15:47:56 EDT 2003


Update of /cvs-repository/ZODB3/ZEO/zrpc
In directory cvs.zope.org:/tmp/cvs-serv32190

Modified Files:
      Tag: Zope-2_7-branch
	smac.py 
Log Message:
Split single HMAC object into two: one for sends, one for receives.

I couldn't come up with a simple test that failed before this change,
although I expect it is possible.  Would be good to do that
eventually.


=== ZODB3/ZEO/zrpc/smac.py 1.38.6.2 => 1.38.6.3 ===
--- ZODB3/ZEO/zrpc/smac.py:1.38.6.2	Fri Sep 19 15:01:28 2003
+++ ZODB3/ZEO/zrpc/smac.py	Fri Sep 19 15:47:56 2003
@@ -96,12 +96,33 @@
         self.__output_lock = threading.Lock() # Protects __output
         self.__output = []
         self.__closed = 0
-        self.__hmac = None
+        # Each side of the connection sends and receives messages.  A
+        # MAC is generated for each message and depends on each
+        # previous MAC; the state of the MAC generator depends on the
+        # history of operations it has performed.  So the MACs must be
+        # generated in the same order they are verified.
+        
+        # Each side is guaranteed to receive messages in the order
+        # they are sent, but there is no ordering constraint between
+        # message sends and receives.  If the two sides are A and B
+        # and message An indicates the nth message sent by A, then
+        # A1 A2 B1 B2 and A1 B1 B2 A2 are both legitimate total
+        # orderings of the messages.
+
+        # As a result, there must be seperate MAC generators for each
+        # side of the connection.  If not, the generator state would
+        # be different after A1 A2 B1 B2 than it would be after
+        # A1 B1 B2 A2; if the generator state was different, the MAC
+        # could not be verified.
+        self.__hmac_send = None
+        self.__hmac_recv = None
+        
         self.__super_init(sock, map)
 
     def setSessionKey(self, sesskey):
         log("set session key %r" % sesskey)
-        self.__hmac = hmac.HMAC(sesskey, digestmod=sha)
+        self.__hmac_send = hmac.HMAC(sesskey, digestmod=sha)
+        self.__hmac_recv = hmac.HMAC(sesskey, digestmod=sha)
 
     def get_addr(self):
         return self.addr
@@ -160,7 +181,7 @@
                     if has_mac:
                         msg_size ^= MAC_BIT
                         msg_size += 20
-                    elif self.__hmac:
+                    elif self.__hmac_send:
                         raise ValueError("Received message without MAC")
                     state = 1
                 else:
@@ -179,9 +200,9 @@
                     if has_mac:
                         mac = msg[:20]
                         msg = msg[20:]
-                        if self.__hmac:
-                            self.__hmac.update(msg)
-                            _mac = self.__hmac.digest()
+                        if self.__hmac_recv:
+                            self.__hmac_recv.update(msg)
+                            _mac = self.__hmac_recv.digest()
                             if mac != _mac:
                                 raise ValueError("MAC failed: %r != %r"
                                                  % (_mac, mac))
@@ -247,8 +268,9 @@
     def message_output(self, message):
         if __debug__:
             if self._debug:
-                log("message_output %d bytes: %s" %
-                    (len(message), short_repr(message)),
+                log("message_output %d bytes: %s hmac=%d" %
+                    (len(message), short_repr(message),
+                    self.__hmac_send and 1 or 0),
                     level=zLOG.TRACE)
 
         if self.__closed:
@@ -257,10 +279,10 @@
         self.__output_lock.acquire()
         try:
             # do two separate appends to avoid copying the message string
-            if self.__hmac:
+            if self.__hmac_send:
                 self.__output.append(struct.pack(">I", len(message) | MAC_BIT))
-                self.__hmac.update(message)
-                self.__output.append(self.__hmac.digest())
+                self.__hmac_send.update(message)
+                self.__output.append(self.__hmac_send.digest())
             else:
                 self.__output.append(struct.pack(">I", len(message)))
             if len(message) <= SEND_SIZE:




More information about the Zope-Checkins mailing list