1/*
2 Copyright (c) 2007-2019 Contributors as noted in the AUTHORS file
3
4 This file is part of libzmq, the ZeroMQ core engine in C++.
5
6 libzmq is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License (LGPL) as published
8 by the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 As a special exception, the Contributors give you permission to link
12 this library with independent modules to produce an executable,
13 regardless of the license terms of these independent modules, and to
14 copy and distribute the resulting executable under terms of your choice,
15 provided that you also meet, for each linked independent module, the
16 terms and conditions of the license of that module. An independent
17 module is a module which is not derived from or based on this library.
18 If you modify this library, you must extend this exception to your
19 version of the library.
20
21 libzmq is distributed in the hope that it will be useful, but WITHOUT
22 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
24 License for more details.
25
26 You should have received a copy of the GNU Lesser General Public License
27 along with this program. If not, see <http://www.gnu.org/licenses/>.
28*/
29#include "testutil_security.hpp"
30
31#include <stdlib.h>
32#include <string.h>
33
34const char *test_zap_domain = "ZAPTEST";
35
36void socket_config_null_client (void *server_, void *server_secret_)
37{
38 LIBZMQ_UNUSED (server_);
39 LIBZMQ_UNUSED (server_secret_);
40}
41
42void socket_config_null_server (void *server_, void *server_secret_)
43{
44 TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
45 server_, ZMQ_ZAP_DOMAIN, test_zap_domain, strlen (test_zap_domain)));
46#ifdef ZMQ_ZAP_ENFORCE_DOMAIN
47 int required = server_secret_ ? *static_cast<int *> (server_secret_) : 0;
48 TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (server_, ZMQ_ZAP_ENFORCE_DOMAIN,
49 &required, sizeof (int)));
50#else
51 LIBZMQ_UNUSED (server_secret_);
52#endif
53}
54
55static const char test_plain_username[] = "testuser";
56static const char test_plain_password[] = "testpass";
57
58void socket_config_plain_client (void *server_, void *server_secret_)
59{
60 LIBZMQ_UNUSED (server_secret_);
61
62 TEST_ASSERT_SUCCESS_ERRNO (
63 zmq_setsockopt (server_, ZMQ_PLAIN_PASSWORD, test_plain_password, 8));
64 TEST_ASSERT_SUCCESS_ERRNO (
65 zmq_setsockopt (server_, ZMQ_PLAIN_USERNAME, test_plain_username, 8));
66}
67
68void socket_config_plain_server (void *server_, void *server_secret_)
69{
70 LIBZMQ_UNUSED (server_secret_);
71
72 int as_server = 1;
73 TEST_ASSERT_SUCCESS_ERRNO (
74 zmq_setsockopt (server_, ZMQ_PLAIN_SERVER, &as_server, sizeof (int)));
75 TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
76 server_, ZMQ_ZAP_DOMAIN, test_zap_domain, strlen (test_zap_domain)));
77}
78
79char valid_client_public[41];
80char valid_client_secret[41];
81char valid_server_public[41];
82char valid_server_secret[41];
83
84void setup_testutil_security_curve ()
85{
86 // Generate new keypairs for these tests
87 TEST_ASSERT_SUCCESS_ERRNO (
88 zmq_curve_keypair (valid_client_public, valid_client_secret));
89 TEST_ASSERT_SUCCESS_ERRNO (
90 zmq_curve_keypair (valid_server_public, valid_server_secret));
91}
92
93void socket_config_curve_server (void *server_, void *server_secret_)
94{
95 int as_server = 1;
96 TEST_ASSERT_SUCCESS_ERRNO (
97 zmq_setsockopt (server_, ZMQ_CURVE_SERVER, &as_server, sizeof (int)));
98 TEST_ASSERT_SUCCESS_ERRNO (
99 zmq_setsockopt (server_, ZMQ_CURVE_SECRETKEY, server_secret_, 41));
100 TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
101 server_, ZMQ_ZAP_DOMAIN, test_zap_domain, strlen (test_zap_domain)));
102
103#ifdef ZMQ_ZAP_ENFORCE_DOMAIN
104 int required = 1;
105 TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (server_, ZMQ_ZAP_ENFORCE_DOMAIN,
106 &required, sizeof (int)));
107#endif
108}
109
110void socket_config_curve_client (void *client_, void *data_)
111{
112 curve_client_data_t *curve_client_data =
113 static_cast<curve_client_data_t *> (data_);
114
115 TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
116 client_, ZMQ_CURVE_SERVERKEY, curve_client_data->server_public, 41));
117 TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
118 client_, ZMQ_CURVE_PUBLICKEY, curve_client_data->client_public, 41));
119 TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
120 client_, ZMQ_CURVE_SECRETKEY, curve_client_data->client_secret, 41));
121}
122
123void *zap_requests_handled;
124
125void zap_handler_generic (zap_protocol_t zap_protocol_,
126 const char *expected_routing_id_)
127{
128 void *control = zmq_socket (get_test_context (), ZMQ_REQ);
129 TEST_ASSERT_NOT_NULL (control);
130 TEST_ASSERT_SUCCESS_ERRNO (
131 zmq_connect (control, "inproc://handler-control"));
132
133 void *handler = zmq_socket (get_test_context (), ZMQ_REP);
134 TEST_ASSERT_NOT_NULL (handler);
135 TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (handler, "inproc://zeromq.zap.01"));
136
137 // Signal main thread that we are ready
138 send_string_expect_success (control, "GO", 0);
139
140 zmq_pollitem_t items[] = {
141 {control, 0, ZMQ_POLLIN, 0},
142 {handler, 0, ZMQ_POLLIN, 0},
143 };
144
145 // if ordered not to receive the request, ignore the second poll item
146 const int numitems = (zap_protocol_ == zap_do_not_recv) ? 1 : 2;
147
148 // Process ZAP requests forever
149 while (zmq_poll (items, numitems, -1) >= 0) {
150 if (items[0].revents & ZMQ_POLLIN) {
151 recv_string_expect_success (control, "STOP", 0);
152 break; // Terminating - main thread signal
153 }
154 if (!(items[1].revents & ZMQ_POLLIN))
155 continue;
156
157 char *version = s_recv (handler);
158 if (!version)
159 break; // Terminating - peer's socket closed
160 if (zap_protocol_ == zap_disconnect) {
161 free (version);
162 break;
163 }
164
165 char *sequence = s_recv (handler);
166 char *domain = s_recv (handler);
167 char *address = s_recv (handler);
168 char *routing_id = s_recv (handler);
169 char *mechanism = s_recv (handler);
170 bool authentication_succeeded = false;
171 if (streq (mechanism, "CURVE")) {
172 uint8_t client_key[32];
173 TEST_ASSERT_EQUAL_INT (32, TEST_ASSERT_SUCCESS_ERRNO (zmq_recv (
174 handler, client_key, 32, 0)));
175
176 char client_key_text[41];
177 zmq_z85_encode (client_key_text, client_key, 32);
178
179 authentication_succeeded =
180 streq (client_key_text, valid_client_public);
181 } else if (streq (mechanism, "PLAIN")) {
182 char client_username[32];
183 int size = TEST_ASSERT_SUCCESS_ERRNO (
184 zmq_recv (handler, client_username, 32, 0));
185 client_username[size] = 0;
186
187 char client_password[32];
188 size = TEST_ASSERT_SUCCESS_ERRNO (
189 zmq_recv (handler, client_password, 32, 0));
190 client_password[size] = 0;
191
192 authentication_succeeded =
193 streq (test_plain_username, client_username)
194 && streq (test_plain_password, client_password);
195 } else if (streq (mechanism, "NULL")) {
196 authentication_succeeded = true;
197 } else {
198 char msg[128];
199 printf ("Unsupported mechanism: %s\n", mechanism);
200 TEST_FAIL_MESSAGE (msg);
201 }
202
203 TEST_ASSERT_EQUAL_STRING ("1.0", version);
204 TEST_ASSERT_EQUAL_STRING (expected_routing_id_, routing_id);
205
206 send_string_expect_success (
207 handler,
208 zap_protocol_ == zap_wrong_version ? "invalid_version" : version,
209 ZMQ_SNDMORE);
210 send_string_expect_success (handler,
211 zap_protocol_ == zap_wrong_request_id
212 ? "invalid_request_id"
213 : sequence,
214 ZMQ_SNDMORE);
215
216 if (authentication_succeeded) {
217 const char *status_code;
218 switch (zap_protocol_) {
219 case zap_status_internal_error:
220 status_code = "500";
221 break;
222 case zap_status_temporary_failure:
223 status_code = "300";
224 break;
225 case zap_status_invalid:
226 status_code = "invalid_status";
227 break;
228 default:
229 status_code = "200";
230 }
231 send_string_expect_success (handler, status_code, ZMQ_SNDMORE);
232 send_string_expect_success (handler, "OK", ZMQ_SNDMORE);
233 send_string_expect_success (handler, "anonymous", ZMQ_SNDMORE);
234 if (zap_protocol_ == zap_too_many_parts) {
235 send_string_expect_success (handler, "", ZMQ_SNDMORE);
236 }
237 if (zap_protocol_ != zap_do_not_send)
238 send_string_expect_success (handler, "", 0);
239 } else {
240 send_string_expect_success (handler, "400", ZMQ_SNDMORE);
241 send_string_expect_success (handler, "Invalid client public key",
242 ZMQ_SNDMORE);
243 send_string_expect_success (handler, "", ZMQ_SNDMORE);
244 if (zap_protocol_ != zap_do_not_send)
245 send_string_expect_success (handler, "", 0);
246 }
247 free (version);
248 free (sequence);
249 free (domain);
250 free (address);
251 free (routing_id);
252 free (mechanism);
253
254 zmq_atomic_counter_inc (zap_requests_handled);
255 }
256 TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (handler, "inproc://zeromq.zap.01"));
257 close_zero_linger (handler);
258
259 if (zap_protocol_ != zap_disconnect) {
260 send_string_expect_success (control, "STOPPED", 0);
261 }
262 close_zero_linger (control);
263}
264
265void zap_handler (void *)
266{
267 zap_handler_generic (zap_ok);
268}
269
270static void setup_handshake_socket_monitor (void *server_,
271 void **server_mon_,
272 const char *monitor_endpoint_)
273{
274 // Monitor handshake events on the server
275 TEST_ASSERT_SUCCESS_ERRNO (zmq_socket_monitor (
276 server_, monitor_endpoint_,
277 ZMQ_EVENT_HANDSHAKE_SUCCEEDED | ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL
278 | ZMQ_EVENT_HANDSHAKE_FAILED_AUTH
279 | ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL));
280
281 // Create socket for collecting monitor events
282 *server_mon_ = test_context_socket (ZMQ_PAIR);
283 int linger = 0;
284 TEST_ASSERT_SUCCESS_ERRNO (
285 zmq_setsockopt (*server_mon_, ZMQ_LINGER, &linger, sizeof (linger)));
286
287 // Connect it to the inproc endpoints so they'll get events
288 TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (*server_mon_, monitor_endpoint_));
289}
290
291void setup_context_and_server_side (void **zap_control_,
292 void **zap_thread_,
293 void **server_,
294 void **server_mon_,
295 char *my_endpoint_,
296 zmq_thread_fn zap_handler_,
297 socket_config_fn socket_config_,
298 void *socket_config_data_,
299 const char *routing_id_)
300{
301 // Spawn ZAP handler
302 zap_requests_handled = zmq_atomic_counter_new ();
303 TEST_ASSERT_NOT_NULL (zap_requests_handled);
304
305 *zap_control_ = test_context_socket (ZMQ_REP);
306 TEST_ASSERT_SUCCESS_ERRNO (
307 zmq_bind (*zap_control_, "inproc://handler-control"));
308 int linger = 0;
309 TEST_ASSERT_SUCCESS_ERRNO (
310 zmq_setsockopt (*zap_control_, ZMQ_LINGER, &linger, sizeof (linger)));
311
312 if (zap_handler_ != NULL) {
313 *zap_thread_ = zmq_threadstart (zap_handler_, NULL);
314
315 recv_string_expect_success (*zap_control_, "GO", 0);
316 } else
317 *zap_thread_ = NULL;
318
319 // Server socket will accept connections
320 *server_ = test_context_socket (ZMQ_DEALER);
321 TEST_ASSERT_SUCCESS_ERRNO (
322 zmq_setsockopt (*server_, ZMQ_LINGER, &linger, sizeof (linger)));
323
324 socket_config_ (*server_, socket_config_data_);
325
326 TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
327 *server_, ZMQ_ROUTING_ID, routing_id_, strlen (routing_id_)));
328
329 bind_loopback_ipv4 (*server_, my_endpoint_, MAX_SOCKET_STRING);
330
331 const char server_monitor_endpoint[] = "inproc://monitor-server";
332 setup_handshake_socket_monitor (*server_, server_mon_,
333 server_monitor_endpoint);
334}
335
336void shutdown_context_and_server_side (void *zap_thread_,
337 void *server_,
338 void *server_mon_,
339 void *zap_control_,
340 bool zap_handler_stopped_)
341{
342 if (zap_thread_ && !zap_handler_stopped_) {
343 send_string_expect_success (zap_control_, "STOP", 0);
344 recv_string_expect_success (zap_control_, "STOPPED", 0);
345 TEST_ASSERT_SUCCESS_ERRNO (
346 zmq_unbind (zap_control_, "inproc://handler-control"));
347 }
348 test_context_socket_close (zap_control_);
349 test_context_socket_close (server_mon_);
350 test_context_socket_close (server_);
351
352 // Wait until ZAP handler terminates
353 if (zap_thread_)
354 zmq_threadclose (zap_thread_);
355
356 zmq_atomic_counter_destroy (&zap_requests_handled);
357}
358
359void *create_and_connect_client (char *my_endpoint_,
360 socket_config_fn socket_config_,
361 void *socket_config_data_,
362 void **client_mon_)
363{
364 void *client = test_context_socket (ZMQ_DEALER);
365
366 socket_config_ (client, socket_config_data_);
367
368 TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint_));
369
370 if (client_mon_) {
371 setup_handshake_socket_monitor (client, client_mon_,
372 "inproc://client-monitor");
373 }
374
375 return client;
376}
377
378void expect_new_client_bounce_fail (char *my_endpoint_,
379 void *server_,
380 socket_config_fn socket_config_,
381 void *socket_config_data_,
382 void **client_mon_,
383 int expected_client_event_,
384 int expected_client_value_)
385{
386 void *my_client_mon = NULL;
387 TEST_ASSERT_TRUE (client_mon_ == NULL || expected_client_event_ == 0);
388 if (expected_client_event_ != 0)
389 client_mon_ = &my_client_mon;
390 void *client = create_and_connect_client (my_endpoint_, socket_config_,
391 socket_config_data_, client_mon_);
392 expect_bounce_fail (server_, client);
393
394 if (expected_client_event_ != 0) {
395 int events_received = 0;
396 events_received = expect_monitor_event_multiple (
397 my_client_mon, expected_client_event_, expected_client_value_, false);
398
399 TEST_ASSERT_EQUAL_INT (1, events_received);
400
401 test_context_socket_close (my_client_mon);
402 }
403
404 test_context_socket_close_zero_linger (client);
405}
406