Re: Creating proxies with different hmac_key
Giovanni Porcari <[email protected]> Wed, 30 Oct 2013 00:15:37 +0100
| Newsgroups | gmane.comp.python.pyro |
|---|---|
| Message-ID | <[email protected]> |
Il giorno 29/ott/2013, alle ore 20:39, Irmen de Jong <[email protected]> ha scritto: > On 29-10-2013 11:11, Giovanni Porcari wrote: >> Hi all >> >> i am using pyro4 and I should connect to different pyro4 daemons in different servers >> that uses different hmac_keys. >> >> So I would like to write : >> >> proxy_to_foo = Pyro4.Proxy(uri_foo,hmac_key='myfookey') >> proxy_to_bar = Pyro4.Proxy(uri_bar,hmac_key='mybarkey') >> >> But unfortunately i can only use Pyro4.config.HMAC_KEY= 'mykey' >> >> Any suggestion ? >> > > This is not possible at this time. > > It is on the TODO list though. With an equally likely alternative to remove the HMAC in > its current form altogether. Would you miss it if it is gone? > > Irmen > Hi Irmen I think that HMAC feature offers us a bit more secure connections so i really prefer to have it. In last hours I had a very quick look to the code and i tried to add this feature (maybe in an ugly way...). It seems working to me but of course I am eager to know your opinion. Thank you for your work :) G. ------------------------------------------------------------------------------ Android is increasing in popularity, but the open development platform that developers love is also attractive to malware creators. Download this white paper to learn more about secure code signing practices that can help keep Android apps secure. http://pubads.g.doubleclick.net/gampad/clk?id=65839951&iu=/4140/ostg.clktrk _______________________________________________ Pyro-core mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/pyro-core
patch.diff
(application/octet-stream, 7.2 KB)
diff --git a/src/Pyro4/core.py b/src/Pyro4/core.py
index 2087a05..824f054 100644
--- a/src/Pyro4/core.py
+++ b/src/Pyro4/core.py
@@ -176,9 +176,9 @@ class Proxy(object):
.. automethod:: _pyroBatch
.. automethod:: _pyroAsync
"""
- __pyroAttributes=frozenset(["__getnewargs__", "__getinitargs__", "_pyroConnection", "_pyroUri", "_pyroOneway", "_pyroTimeout", "_pyroSeq"])
+ __pyroAttributes=frozenset(["__getnewargs__", "__getinitargs__", "_pyroHmacKey", "_pyroConnection", "_pyroUri", "_pyroOneway", "_pyroTimeout", "_pyroSeq"])
- def __init__(self, uri):
+ def __init__(self, uri, hmac_key=None):
"""
.. autoattribute:: _pyroOneway
.. autoattribute:: _pyroTimeout
@@ -189,12 +189,14 @@ class Proxy(object):
elif not isinstance(uri, URI):
raise TypeError("expected Pyro URI")
self._pyroUri=uri
+ self._pyroHmacKey=hmac_key
self._pyroConnection=None
self._pyroOneway=set()
self._pyroSeq=0 # message sequence number
self.__pyroTimeout=Pyro4.config.COMMTIMEOUT
self.__pyroLock=threadutil.Lock()
self.__pyroConnLock=threadutil.Lock()
+
util.get_serializer(Pyro4.config.SERIALIZER) # assert that the configured serializer is available
if os.name=="java" and Pyro4.config.SERIALIZER=="marshal":
import warnings
@@ -296,14 +298,14 @@ class Proxy(object):
self._pyroSeq=(self._pyroSeq+1)&0xffff
if Pyro4.config.LOGWIRE:
log.debug("proxy wiredata sending: msgtype=%d flags=0x%x ser=%d seq=%d data=%r" % (Pyro4.message.MSG_INVOKE, flags, serializer.serializer_id, self._pyroSeq, data))
- msg = Message(Pyro4.message.MSG_INVOKE, data, serializer.serializer_id, flags, self._pyroSeq)
+ msg = Message(Pyro4.message.MSG_INVOKE, data, serializer.serializer_id, flags, self._pyroSeq, hmac_key= self._pyroHmacKey)
try:
self._pyroConnection.send(msg.to_bytes())
del msg # invite GC to collect the object, don't wait for out-of-scope
if flags & Pyro4.message.FLAGS_ONEWAY:
return None # oneway call, no response data
else:
- msg = Message.recv(self._pyroConnection, [Pyro4.message.MSG_RESULT])
+ msg = Message.recv(self._pyroConnection, [Pyro4.message.MSG_RESULT],hmac_key=self._pyroHmacKey)
if Pyro4.config.LOGWIRE:
log.debug("proxy wiredata received: msgtype=%d flags=0x%x ser=%d seq=%d data=%r" % (msg.type, msg.flags, msg.serializer_id, msg.seq, msg.data) )
self.__pyroCheckSequence(msg.seq)
@@ -355,7 +357,7 @@ class Proxy(object):
sock=socketutil.createSocket(connect=connect_location, reuseaddr=Pyro4.config.SOCK_REUSE, timeout=self.__pyroTimeout)
conn=socketutil.SocketConnection(sock, uri.object)
# Do handshake. For now, no need to send anything. (message type CONNECT is not yet used)
- msg = Message.recv(conn, None)
+ msg = Message.recv(conn, None,hmac_key=self._pyroHmacKey)
# any trailing data (dataLen>0) is an error message, if any
except Exception:
x=sys.exc_info()[1]
diff --git a/src/Pyro4/message.py b/src/Pyro4/message.py
index 5f45f4b..c77f46f 100755
--- a/src/Pyro4/message.py
+++ b/src/Pyro4/message.py
@@ -78,12 +78,12 @@ class Message(object):
An 'HMAC' annotation chunk contains the hmac digest of the message data bytes and
all of the annotation chunk data bytes (except those of the HMAC chunk itself).
"""
- __slots__ = ["type", "flags", "seq", "data", "data_size", "serializer_id", "annotations", "annotations_size"]
+ __slots__ = ["type", "flags", "seq", "data", "data_size", "serializer_id", "annotations", "annotations_size","hmac_key"]
header_format = '!4sHHHHiHHHH'
header_size = struct.calcsize(header_format)
checksum_magic = 0x34E9
- def __init__(self, msgType, databytes, serializer_id, flags, seq, annotations=None):
+ def __init__(self, msgType, databytes, serializer_id, flags, seq, annotations=None,hmac_key=None):
self.type = msgType
self.flags = flags
self.seq = seq
@@ -91,8 +91,9 @@ class Message(object):
self.data_size = len(self.data)
self.serializer_id = serializer_id
self.annotations = annotations or {}
- if Pyro4.config.HMAC_KEY:
- self.annotations["HMAC"] = self.hmac()
+ self.hmac_key=hmac_key or Pyro4.config.HMAC_KEY
+ if self.hmac_key:
+ self.annotations["HMAC"] = self.hmac(hmac_key=self.hmac_key)
self.annotations_size = sum([6+len(v) for v in self.annotations.values()])
if 0 < Pyro4.config.MAX_MESSAGE_SIZE < (self.data_size + self.annotations_size):
raise errors.ProtocolError("max message size exceeded (%d where max=%d)" % (self.data_size+self.annotations_size, Pyro4.config.MAX_MESSAGE_SIZE))
@@ -150,13 +151,14 @@ class Message(object):
return msg
@classmethod
- def recv(cls, connection, requiredMsgTypes=None):
+ def recv(cls, connection, requiredMsgTypes=None, hmac_key=None):
"""
Receives a pyro message from a given connection.
Accepts the given message types (None=any, or pass a sequence).
Also reads annotation chunks and the actual payload data.
Validates a HMAC chunk if present.
"""
+ hmac_key=hmac_key or Pyro4.config.HMAC_KEY
msg = cls.from_header(connection.recv(cls.header_size))
if 0 < Pyro4.config.MAX_MESSAGE_SIZE < (msg.data_size+msg.annotations_size):
errorMsg = "max message size exceeded (%d where max=%d)" % (msg.data_size+msg.annotations_size, Pyro4.config.MAX_MESSAGE_SIZE)
@@ -180,20 +182,22 @@ class Message(object):
i += 6+length
# read data
msg.data = connection.recv(msg.data_size)
- if "HMAC" in msg.annotations and Pyro4.config.HMAC_KEY:
- if msg.annotations["HMAC"] != msg.hmac():
+ if "HMAC" in msg.annotations and hmac_key:
+ if msg.annotations["HMAC"] != msg.hmac(hmac_key=hmac_key):
raise errors.SecurityError("message hmac mismatch")
- elif ("HMAC" in msg.annotations) != bool(Pyro4.config.HMAC_KEY):
+ elif ("HMAC" in msg.annotations) != bool(hmac_key):
# Message contains hmac and local HMAC_KEY not set, or vice versa. This is not allowed.
err = "hmac key config not symmetric"
log.warning(err)
raise errors.SecurityError(err)
return msg
- def hmac(self):
+ def hmac(self,hmac_key=None):
"""returns the hmac of the data and the annotation chunk values (except HMAC chunk itself)"""
- mac = hmac.new(Pyro4.config.HMAC_KEY, self.data, digestmod=hashlib.sha1)
+ hmac_key=hmac_key or Pyro4.config.HMAC_KEY
+ mac = hmac.new(hmac_key, self.data, digestmod=hashlib.sha1)
for k, v in self.annotations.items():
if k != "HMAC":
mac.update(v)
return mac.digest()
+