[zeromq-dev] pyzmq curve example code
Greg Ward
greg at gerg.ca
Tue Feb 25 23:09:58 CET 2014
On 25 February 2014, To ZeroMQ development list said:
> But that seems to have decayed somewhat. I noticed an error from
> pyzmq's setup script about libsodium in the umpteenth build yesterday.
> I think maybe I'll start from scratch with a fresh prefix dir and see
> if that clarifies things.
OK I've updated libsodium, libzmq, and pyzmq from git master, rebuilt
and reinstalled everything to a fresh prefix (/usr/local/zmq4).
Building pyzmq ("python setup.py build --zmq=/usr/local/zmq4") printed
Warning: Detected ZMQ version: 4.1.0. pyzmq's support for libzmq-dev is experimental.
but what the hell, I'm gonna barge on past that and take a chance. I
saw no warnings about curve or libsodium.
Now I have three problems in examples/security:
1) strawhouse succeeds but logs an error:
$ python strawhouse.py
[ERROR] Failed to deny [u'127.0.0.1']
Traceback (most recent call last):
File "/usr/local/zmq4/lib/python2.7/site-packages/zmq/auth/thread.py", line 97, in _handle_pipe
self.authenticator.deny(*addresses)
File "/usr/local/zmq4/lib/python2.7/site-packages/zmq/auth/base.py", line 85, in deny
raise ValueError("Only use a whitelist or a blacklist, not both")
ValueError: Only use a whitelist or a blacklist, not both
[INFO] Strawhouse test OK
(I didn't see this yesterday; unclear what has changed -- except
I'm now linking with latest upstream libzmq)
2) stonehouse.py refers to the wrong script:
$ python stonehouse.py
[CRITICAL] Certificates are missing - run generate_certificates script first
(https://github.com/zeromq/pyzmq/pull/480)
(I saw this yesterday, so today I thought I'd fix it)
3) generate_keys.py still crashes mysteriously:
$ python generate_keys.py
Traceback (most recent call last):
File "generate_keys.py", line 49, in <module>
generate_certificates(os.path.dirname(__file__))
File "generate_keys.py", line 30, in generate_certificates
server_public_file, server_secret_file = zmq.auth.create_certificates(keys_dir, "server")
File "/usr/local/zmq4/lib/python2.7/site-packages/zmq/auth/certs.py", line 67, in create_certificates
public_key, secret_key = zmq.curve_keypair()
File "utils.pyx", line 51, in zmq.backend.cython.utils.curve_keypair (zmq/backend/cython/utils.c:762)
File "/usr/local/zmq4/lib/python2.7/site-packages/zmq/error.py", line 128, in _check_rc
raise ZMQError(errno)
zmq.error.ZMQError: No such file or directory
(same problem as yesterday)
So I've dug in a little bit, and it looks like something is
incorrectly reusing errno. Evidence: I hacked
zmq/backend/cython/utils.py as follows:
--- a/zmq/backend/cython/utils.pyx
+++ b/zmq/backend/cython/utils.pyx
@@ -44,10 +44,16 @@ def curve_keypair():
(public, secret) : two bytestrings
The public and private keypair as 40 byte z85-encoded bytestrings.
"""
+ import os, signal
cdef int rc
cdef char[64] public_key
cdef char[64] secret_key
+ print('calling zmq_curve_keypair(%r, %r)' % (public_key, secret_key))
+ pid = os.getpid()
+ print('sudo strace -f -tt -p %d' % pid)
+ os.kill(pid, signal.SIGSTOP)
rc = zmq_curve_keypair (public_key, secret_key)
+ print('zmq_curve_keypair() = %r' % rc)
_check_rc(rc)
return public_key, secret_key
This gives me:
* the opportunity to strace (in another terminal window) starting
from just before the mysterious error
* clear indicators (write() to stdout) before and after the error
So I run generate_keys.py with the hacked utils.pyx:
$ python generate_keys.py
calling zmq_curve_keypair('P\xc4X', '')
sudo strace -f -tt -p 14453
zsh: suspended (signal) python generate_keys.py
In another window, I run the suggested strace command. Then I "fg"
generate_keys.py. Here's what strace reports:
$ sudo strace -f -tt -p 14391
Process 14391 attached
16:58:05.345389 --- stopped by SIGSTOP ---
16:58:08.518451 --- SIGCONT {si_signo=SIGCONT, si_code=SI_USER, si_pid=13915, si_uid=1554} ---
16:58:08.518662 write(1, "zmq_curve_keypair() = -1\n", 25) = 25
16:58:08.518989 stat("/data/src/pyzmq/build/lib.linux-x86_64-2.7/zmq/errno", 0x7fff9e5fa630) = -1 ENOENT (No such file or directory)
16:58:08.519254 open("/data/src/pyzmq/build/lib.linux-x86_64-2.7/zmq/errno.x86_64-linux-gnu.so", O_RDONLY) = -1 ENOENT (No such file or directory)
16:58:08.519508 open("/data/src/pyzmq/build/lib.linux-x86_64-2.7/zmq/errno.so", O_RDONLY) = -1 ENOENT (No such file or directory)
16:58:08.519722 open("/data/src/pyzmq/build/lib.linux-x86_64-2.7/zmq/errnomodule.so", O_RDONLY) = -1 ENOENT (No such file or directory)
16:58:08.519888 open("/data/src/pyzmq/build/lib.linux-x86_64-2.7/zmq/errno.py", O_RDONLY) = -1 ENOENT (No such file or directory)
16:58:08.520011 open("/data/src/pyzmq/build/lib.linux-x86_64-2.7/zmq/errno.pyc", O_RDONLY) = -1 ENOENT (No such file or directory)
16:58:08.520338 write(2, "Traceback (most recent call last"..., 35) = 35
Bingo. The only file I/O in the call to zmq_curve_keypair() is some
Python code trying to import errno (the module). So errno (the C
global variable) is left at ENOENT, which causes _check_rc() to
generate a misleading exception.
Just to confirm, I made it so the last file Python tries to open fails
differently:
$ touch /data/src/pyzmq/build/lib.linux-x86_64-2.7/zmq/errno.pyc
$ chmod 000 /data/src/pyzmq/build/lib.linux-x86_64-2.7/zmq/errno.pyc
$ cat /data/src/pyzmq/build/lib.linux-x86_64-2.7/zmq/errno.pyc
cat: /data/src/pyzmq/build/lib.linux-x86_64-2.7/zmq/errno.pyc: Permission denied
When I run the whole thing again, strace reports:
Process 14405 attached
17:00:00.913494 --- stopped by SIGSTOP ---
17:00:02.679923 --- SIGCONT {si_signo=SIGCONT, si_code=SI_USER, si_pid=13915, si_uid=1554} ---
17:00:02.680118 write(1, "zmq_curve_keypair() = -1\n", 25) = 25
17:00:02.680430 stat("/data/src/pyzmq/build/lib.linux-x86_64-2.7/zmq/errno", 0x7fff0adee750) = -1 ENOENT (No such file or directory)
17:00:02.680792 open("/data/src/pyzmq/build/lib.linux-x86_64-2.7/zmq/errno.x86_64-linux-gnu.so", O_RDONLY) = -1 ENOENT (No such file or directory)
17:00:02.681013 open("/data/src/pyzmq/build/lib.linux-x86_64-2.7/zmq/errno.so", O_RDONLY) = -1 ENOENT (No such file or directory)
17:00:02.681201 open("/data/src/pyzmq/build/lib.linux-x86_64-2.7/zmq/errnomodule.so", O_RDONLY) = -1 ENOENT (No such file or directory)
17:00:02.681312 open("/data/src/pyzmq/build/lib.linux-x86_64-2.7/zmq/errno.py", O_RDONLY) = -1 ENOENT (No such file or directory)
17:00:02.681412 open("/data/src/pyzmq/build/lib.linux-x86_64-2.7/zmq/errno.pyc", O_RDONLY) = -1 EACCES (Permission denied)
17:00:02.681719 write(2, "Traceback (most recent call last"..., 35) = 35
and the exception printed by python is now:
Traceback (most recent call last):
File "generate_keys.py", line 49, in <module>
generate_certificates(os.path.dirname(__file__))
File "generate_keys.py", line 30, in generate_certificates
server_public_file, server_secret_file = zmq.auth.create_certificates(keys_dir, "server")
File "/data/src/pyzmq/build/lib.linux-x86_64-2.7/zmq/auth/certs.py", line 67, in create_certificates
public_key, secret_key = zmq.curve_keypair()
File "utils.pyx", line 57, in zmq.backend.cython.utils.curve_keypair (zmq/backend/cython/utils.c:905)
File "/data/src/pyzmq/build/lib.linux-x86_64-2.7/zmq/error.py", line 128, in _check_rc
raise ZMQError(errno)
zmq.error.ZMQError: Permission denied
I'm slightly stumped. Next step?
Greg
More information about the zeromq-dev
mailing list