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 | |
34 | const char *test_zap_domain = "ZAPTEST" ; |
35 | |
36 | void socket_config_null_client (void *server_, void *server_secret_) |
37 | { |
38 | LIBZMQ_UNUSED (server_); |
39 | LIBZMQ_UNUSED (server_secret_); |
40 | } |
41 | |
42 | void 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 | |
55 | static const char test_plain_username[] = "testuser" ; |
56 | static const char test_plain_password[] = "testpass" ; |
57 | |
58 | void 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 | |
68 | void 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 | |
79 | char valid_client_public[41]; |
80 | char valid_client_secret[41]; |
81 | char valid_server_public[41]; |
82 | char valid_server_secret[41]; |
83 | |
84 | void 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 | |
93 | void 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 | |
110 | void 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 | |
123 | void *zap_requests_handled; |
124 | |
125 | void 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 | |
265 | void zap_handler (void *) |
266 | { |
267 | zap_handler_generic (zap_ok); |
268 | } |
269 | |
270 | static 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 | |
291 | void 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 | |
336 | void 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 | |
359 | void *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 | |
378 | void 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 | |