Skip to content

Commit 1c5a63e

Browse files
committed
Problem: backward incompatible change to NULL with ZAP
Solution: like for other mechanism, do not enforce strict ZAP protocol adherence unless the specific socket option is enabled with NULL auth. Add test to exercise this functionality, and fix ZAP test to set the socket option when it uses NULL auth. See: zeromq/pyzmq#1152
1 parent e4b3bd8 commit 1c5a63e

3 files changed

Lines changed: 67 additions & 19 deletions

File tree

src/null_mechanism.cpp

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -69,24 +69,27 @@ int zmq::null_mechanism_t::next_handshake_command (msg_t *msg_)
6969
errno = EAGAIN;
7070
return -1;
7171
}
72+
// Given this is a backward-incompatible change, it's behind a socket
73+
// option disabled by default.
7274
int rc = session->zap_connect ();
73-
if (rc == -1) {
75+
if (rc == -1 && options.zap_enforce_domain) {
7476
session->get_socket ()->event_handshake_failed_no_detail (
7577
session->get_endpoint (), EFAULT);
7678
return -1;
79+
} else if (rc == 0) {
80+
send_zap_request ();
81+
zap_request_sent = true;
82+
83+
// TODO actually, it is quite unlikely that we can read the ZAP
84+
// reply already, but removing this has some strange side-effect
85+
// (probably because the pipe's in_active flag is true until a read
86+
// is attempted)
87+
rc = receive_and_process_zap_reply ();
88+
if (rc != 0)
89+
return -1;
90+
91+
zap_reply_received = true;
7792
}
78-
send_zap_request ();
79-
zap_request_sent = true;
80-
81-
// TODO actually, it is quite unlikely that we can read the ZAP
82-
// reply already, but removing this has some strange side-effect
83-
// (probably because the pipe's in_active flag is true until a read
84-
// is attempted)
85-
rc = receive_and_process_zap_reply ();
86-
if (rc != 0)
87-
return -1;
88-
89-
zap_reply_received = true;
9093
}
9194

9295
if (zap_reply_received && status_code != "200") {

tests/test_security_null.cpp

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,22 +88,65 @@ int main (void)
8888
void *ctx = zmq_ctx_new ();
8989
assert (ctx);
9090

91+
// We first test client/server with a ZAP domain but with no handler
92+
// If there is no handler, libzmq should ignore the ZAP option unless
93+
// ZMQ_ZAP_ENFORCE_DOMAIN is set
94+
void *server = zmq_socket (ctx, ZMQ_DEALER);
95+
assert (server);
96+
void *client = zmq_socket (ctx, ZMQ_DEALER);
97+
assert (client);
98+
int rc = zmq_setsockopt (server, ZMQ_ZAP_DOMAIN, "TEST", 5);
99+
assert (rc == 0);
100+
rc = zmq_bind (server, "tcp://127.0.0.1:*");
101+
assert (rc == 0);
102+
rc = zmq_getsockopt (server, ZMQ_LAST_ENDPOINT, my_endpoint, &len);
103+
assert (rc == 0);
104+
rc = zmq_connect (client, my_endpoint);
105+
assert (rc == 0);
106+
bounce (server, client);
107+
close_zero_linger (client);
108+
close_zero_linger (server);
109+
110+
#ifdef ZMQ_ZAP_ENFORCE_DOMAIN
111+
// Now set ZMQ_ZAP_ENFORCE_DOMAIN which strictly enforces the ZAP
112+
// RFC but is backward-incompatible, now it should fail
113+
server = zmq_socket (ctx, ZMQ_DEALER);
114+
assert (server);
115+
client = zmq_socket (ctx, ZMQ_DEALER);
116+
assert (client);
117+
int required = 1;
118+
rc =
119+
zmq_setsockopt (server, ZMQ_ZAP_ENFORCE_DOMAIN, &required, sizeof (int));
120+
assert (rc == 0);
121+
rc = zmq_setsockopt (server, ZMQ_ZAP_DOMAIN, "TEST", 5);
122+
assert (rc == 0);
123+
rc = zmq_bind (server, "tcp://127.0.0.1:*");
124+
assert (rc == 0);
125+
rc = zmq_getsockopt (server, ZMQ_LAST_ENDPOINT, my_endpoint, &len);
126+
assert (rc == 0);
127+
rc = zmq_connect (client, my_endpoint);
128+
assert (rc == 0);
129+
expect_bounce_fail (server, client);
130+
close_zero_linger (client);
131+
close_zero_linger (server);
132+
#endif
133+
91134
// Spawn ZAP handler
92135
// We create and bind ZAP socket in main thread to avoid case
93136
// where child thread does not start up fast enough.
94137
void *handler = zmq_socket (ctx, ZMQ_REP);
95138
assert (handler);
96-
int rc = zmq_bind (handler, "inproc://zeromq.zap.01");
139+
rc = zmq_bind (handler, "inproc://zeromq.zap.01");
97140
assert (rc == 0);
98141
void *zap_thread = zmq_threadstart (&zap_handler, handler);
99142

100143
// We bounce between a binding server and a connecting client
101144

102145
// We first test client/server with no ZAP domain
103146
// Libzmq does not call our ZAP handler, the connect must succeed
104-
void *server = zmq_socket (ctx, ZMQ_DEALER);
147+
server = zmq_socket (ctx, ZMQ_DEALER);
105148
assert (server);
106-
void *client = zmq_socket (ctx, ZMQ_DEALER);
149+
client = zmq_socket (ctx, ZMQ_DEALER);
107150
assert (client);
108151
rc = zmq_bind (server, "tcp://127.0.0.1:*");
109152
assert (rc == 0);

tests/test_security_zap.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -326,10 +326,12 @@ void test_zap_errors (socket_config_fn server_socket_config_,
326326

327327
#ifdef ZMQ_ZAP_ENFORCE_DOMAIN
328328
// no ZAP handler
329+
int enforce = 1;
329330
fprintf (stderr, "test_zap_unsuccessful no ZAP handler started\n");
330-
setup_context_and_server_side (&ctx, &handler, &zap_thread, &server,
331-
&server_mon, my_endpoint, NULL,
332-
server_socket_config_);
331+
setup_context_and_server_side (
332+
&ctx, &handler, &zap_thread, &server, &server_mon, my_endpoint, NULL,
333+
server_socket_config_,
334+
server_socket_config_data_ ? server_socket_config_data_ : &enforce);
333335
test_zap_unsuccessful_no_handler (
334336
ctx, my_endpoint, server, server_mon,
335337
#ifdef ZMQ_BUILD_DRAFT_API

0 commit comments

Comments
 (0)