[IPython-dev] pyzmq authentication

MinRK benjaminrk at gmail.com
Wed Jun 1 14:33:33 EDT 2011

On Wed, Jun 1, 2011 at 11:20, Fernando Perez <fperez.net at gmail.com> wrote:
> On Wed, Jun 1, 2011 at 9:41 AM, MinRK <benjaminrk at gmail.com> wrote:
>> What we have currently is extremely primitive, and only meant to
>> protect against accidental execution rather than
>> malicious intrusion. The key is sent and checked with every message.
> If I understand correctly the link Jason sent, and from a quick
> reading of the multiprocessing code, we should be able to use the same
> machinery to avoid sending/receving the keys.  The main functions that
> do the work in MP are in the 'connection' submodule, and they are
> really two standalone functions:
> def deliver_challenge(connection, authkey):
>    import hmac
>    assert isinstance(authkey, bytes)
>    message = os.urandom(MESSAGE_LENGTH)
>    connection.send_bytes(CHALLENGE + message)
>    digest = hmac.new(authkey, message).digest()
>    response = connection.recv_bytes(256)        # reject large message
>    if response == digest:
>        connection.send_bytes(WELCOME)
>    else:
>        connection.send_bytes(FAILURE)
>        raise AuthenticationError('digest received was wrong')
> def answer_challenge(connection, authkey):
>    import hmac
>    assert isinstance(authkey, bytes)
>    message = connection.recv_bytes(256)         # reject large message
>    assert message[:len(CHALLENGE)] == CHALLENGE, 'message = %r' % message
>    message = message[len(CHALLENGE):]
>    digest = hmac.new(authkey, message).digest()
>    connection.send_bytes(digest)
>    response = connection.recv_bytes(256)        # reject large message
>    if response != WELCOME:
>        raise AuthenticationError('digest sent was rejected')
> They work with objects that have a basic socket interface, but
> adapting this to zmq sockets should be possible.  Am I missing
> something?

We have 3 main channels:
Stdin (XREQ-XREQ) (I think?)

Of these, *only* the XREP can authenticate connections.  The reason is
that none of the other sockets actually know where messages came from,
so there's no mechanism for seeing if the sender previously had a
successful handshake because you actually have no idea who the sender

Even the client's XREQ socket cannot authenticate replies, it must
trust that the replies are coming from the kernel.

That said, the only easy one is the one that is the most important -
the Kernel checking requests prior to execution. However, if you have
someone sniffing on the line, it's trivial to spoof an authenticated
socket - just copy the IDENT, which is sent in the clear over the
wire, and the kernel will have exactly no idea that you aren't the
original authenticated client.

ZMQ has no mechanism for dropping connections (because it has no
public notion of connections), so a one-time authenticated connection
essentially turns your one key into a set of keys (the socket
identities), which are still sent over the wire in exactly the same
fashion as the key is now, and just as vulnerable as sending the key
in the clear, except now you have more of them.


> Cheers,
> f

More information about the IPython-dev mailing list