testutil_security.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MPL-2.0 */
2 #include "testutil_security.hpp"
3 
4 #include <stdlib.h>
5 #include <string.h>
6 
7 const char *test_zap_domain = "ZAPTEST";
8 
9 void socket_config_null_client (void *server_, void *server_secret_)
10 {
11  LIBZMQ_UNUSED (server_);
12  LIBZMQ_UNUSED (server_secret_);
13 }
14 
15 void socket_config_null_server (void *server_, void *server_secret_)
16 {
18  server_, ZMQ_ZAP_DOMAIN, test_zap_domain, strlen (test_zap_domain)));
19 #ifdef ZMQ_ZAP_ENFORCE_DOMAIN
20  int required = server_secret_ ? *static_cast<int *> (server_secret_) : 0;
22  &required, sizeof (int)));
23 #else
24  LIBZMQ_UNUSED (server_secret_);
25 #endif
26 }
27 
28 static const char test_plain_username[] = "testuser";
29 static const char test_plain_password[] = "testpass";
30 
31 void socket_config_plain_client (void *server_, void *server_secret_)
32 {
33  LIBZMQ_UNUSED (server_secret_);
34 
39 }
40 
41 void socket_config_plain_server (void *server_, void *server_secret_)
42 {
43  LIBZMQ_UNUSED (server_secret_);
44 
45  int as_server = 1;
47  zmq_setsockopt (server_, ZMQ_PLAIN_SERVER, &as_server, sizeof (int)));
49  server_, ZMQ_ZAP_DOMAIN, test_zap_domain, strlen (test_zap_domain)));
50 }
51 
56 
58 {
59  // Generate new keypairs for these tests
64 }
65 
66 void socket_config_curve_server (void *server_, void *server_secret_)
67 {
68  int as_server = 1;
70  zmq_setsockopt (server_, ZMQ_CURVE_SERVER, &as_server, sizeof (int)));
72  zmq_setsockopt (server_, ZMQ_CURVE_SECRETKEY, server_secret_, 41));
74  server_, ZMQ_ZAP_DOMAIN, test_zap_domain, strlen (test_zap_domain)));
75 
76 #ifdef ZMQ_ZAP_ENFORCE_DOMAIN
77  int required = 1;
79  &required, sizeof (int)));
80 #endif
81 }
82 
83 void socket_config_curve_client (void *client_, void *data_)
84 {
86  static_cast<const curve_client_data_t *> (data_);
87 
94 }
95 
97 
98 void zap_handler_generic (zap_protocol_t zap_protocol_,
99  const char *expected_routing_id_)
100 {
101  void *control = zmq_socket (get_test_context (), ZMQ_REQ);
102  TEST_ASSERT_NOT_NULL (control);
104  zmq_connect (control, "inproc://handler-control"));
105 
108  TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (handler, "inproc://zeromq.zap.01"));
109 
110  // Signal main thread that we are ready
111  send_string_expect_success (control, "GO", 0);
112 
113  zmq_pollitem_t items[] = {
114  {control, 0, ZMQ_POLLIN, 0},
115  {handler, 0, ZMQ_POLLIN, 0},
116  };
117 
118  // if ordered not to receive the request, ignore the second poll item
119  const int numitems = (zap_protocol_ == zap_do_not_recv) ? 1 : 2;
120 
121  // Process ZAP requests forever
122  while (zmq_poll (items, numitems, -1) >= 0) {
123  if (items[0].revents & ZMQ_POLLIN) {
124  recv_string_expect_success (control, "STOP", 0);
125  break; // Terminating - main thread signal
126  }
127  if (!(items[1].revents & ZMQ_POLLIN))
128  continue;
129 
130  char *version = s_recv (handler);
131  if (!version)
132  break; // Terminating - peer's socket closed
133  if (zap_protocol_ == zap_disconnect) {
134  free (version);
135  break;
136  }
137 
138  char *sequence = s_recv (handler);
139  char *domain = s_recv (handler);
140  char *address = s_recv (handler);
141  char *routing_id = s_recv (handler);
142  char *mechanism = s_recv (handler);
143  bool authentication_succeeded = false;
144  if (streq (mechanism, "CURVE")) {
145  uint8_t client_key[32];
147  handler, client_key, 32, 0)));
148 
149  char client_key_text[41];
150  zmq_z85_encode (client_key_text, client_key, 32);
151 
152  authentication_succeeded =
153  streq (client_key_text, valid_client_public);
154  } else if (streq (mechanism, "PLAIN")) {
155  char client_username[32];
157  zmq_recv (handler, client_username, 32, 0));
158  client_username[size] = 0;
159 
160  char client_password[32];
162  zmq_recv (handler, client_password, 32, 0));
163  client_password[size] = 0;
164 
165  authentication_succeeded =
166  streq (test_plain_username, client_username)
167  && streq (test_plain_password, client_password);
168  } else if (streq (mechanism, "NULL")) {
169  authentication_succeeded = true;
170  } else {
171  char msg[128];
172  printf ("Unsupported mechanism: %s\n", mechanism);
173  TEST_FAIL_MESSAGE (msg);
174  }
175 
177  TEST_ASSERT_EQUAL_STRING (expected_routing_id_, routing_id);
178 
180  handler,
181  zap_protocol_ == zap_wrong_version ? "invalid_version" : version,
182  ZMQ_SNDMORE);
184  zap_protocol_ == zap_wrong_request_id
185  ? "invalid_request_id"
186  : sequence,
187  ZMQ_SNDMORE);
188 
189  if (authentication_succeeded) {
190  const char *status_code;
191  switch (zap_protocol_) {
193  status_code = "500";
194  break;
196  status_code = "300";
197  break;
198  case zap_status_invalid:
199  status_code = "invalid_status";
200  break;
201  default:
202  status_code = "200";
203  }
207  if (zap_protocol_ == zap_too_many_parts) {
209  }
210  if (zap_protocol_ != zap_do_not_send)
212  } else {
214  send_string_expect_success (handler, "Invalid client public key",
215  ZMQ_SNDMORE);
217  if (zap_protocol_ != zap_do_not_send)
219  }
220  free (version);
221  free (sequence);
222  free (domain);
223  free (address);
224  free (routing_id);
225  free (mechanism);
226 
228  }
229  TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (handler, "inproc://zeromq.zap.01"));
231 
232  if (zap_protocol_ != zap_disconnect) {
233  send_string_expect_success (control, "STOPPED", 0);
234  }
235  close_zero_linger (control);
236 }
237 
238 void zap_handler (void *)
239 {
241 }
242 
243 static void setup_handshake_socket_monitor (void *server_,
244  void **server_mon_,
245  const char *monitor_endpoint_)
246 {
247  // Monitor handshake events on the server
249  server_, monitor_endpoint_,
253 
254  // Create socket for collecting monitor events
255  *server_mon_ = test_context_socket (ZMQ_PAIR);
256  int linger = 0;
258  zmq_setsockopt (*server_mon_, ZMQ_LINGER, &linger, sizeof (linger)));
259 
260  // Connect it to the inproc endpoints so they'll get events
261  TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (*server_mon_, monitor_endpoint_));
262 }
263 
264 void setup_context_and_server_side (void **zap_control_,
265  void **zap_thread_,
266  void **server_,
267  void **server_mon_,
268  char *my_endpoint_,
269  zmq_thread_fn zap_handler_,
270  socket_config_fn socket_config_,
271  void *socket_config_data_,
272  const char *routing_id_)
273 {
274  // Spawn ZAP handler
277 
278  *zap_control_ = test_context_socket (ZMQ_REP);
280  zmq_bind (*zap_control_, "inproc://handler-control"));
281  int linger = 0;
283  zmq_setsockopt (*zap_control_, ZMQ_LINGER, &linger, sizeof (linger)));
284 
285  if (zap_handler_ != NULL) {
286  *zap_thread_ = zmq_threadstart (zap_handler_, NULL);
287 
288  recv_string_expect_success (*zap_control_, "GO", 0);
289  } else
290  *zap_thread_ = NULL;
291 
292  // Server socket will accept connections
293  *server_ = test_context_socket (ZMQ_DEALER);
295  zmq_setsockopt (*server_, ZMQ_LINGER, &linger, sizeof (linger)));
296  // As per API by default there's no limit to the size of a message,
297  // but the sanitizer allocator will barf over a gig or so
298  int64_t max_msg_size = 64 * 1024 * 1024;
300  *server_, ZMQ_MAXMSGSIZE, &max_msg_size, sizeof (int64_t)));
301 
302  socket_config_ (*server_, socket_config_data_);
303 
305  *server_, ZMQ_ROUTING_ID, routing_id_, strlen (routing_id_)));
306 
307  bind_loopback_ipv4 (*server_, my_endpoint_, MAX_SOCKET_STRING);
308 
309  const char server_monitor_endpoint[] = "inproc://monitor-server";
310  setup_handshake_socket_monitor (*server_, server_mon_,
311  server_monitor_endpoint);
312 }
313 
314 void shutdown_context_and_server_side (void *zap_thread_,
315  void *server_,
316  void *server_mon_,
317  void *zap_control_,
318  bool zap_handler_stopped_)
319 {
320  if (zap_thread_ && !zap_handler_stopped_) {
321  send_string_expect_success (zap_control_, "STOP", 0);
322  recv_string_expect_success (zap_control_, "STOPPED", 0);
324  zmq_unbind (zap_control_, "inproc://handler-control"));
325  }
326  test_context_socket_close (zap_control_);
327  zmq_socket_monitor (server_, NULL, 0);
328  test_context_socket_close (server_mon_);
329  test_context_socket_close (server_);
330 
331  // Wait until ZAP handler terminates
332  if (zap_thread_)
333  zmq_threadclose (zap_thread_);
334 
336 }
337 
338 void *create_and_connect_client (char *my_endpoint_,
339  socket_config_fn socket_config_,
340  void *socket_config_data_,
341  void **client_mon_)
342 {
344  // As per API by default there's no limit to the size of a message,
345  // but the sanitizer allocator will barf over a gig or so
346  int64_t max_msg_size = 64 * 1024 * 1024;
348  zmq_setsockopt (client, ZMQ_MAXMSGSIZE, &max_msg_size, sizeof (int64_t)));
349 
350  socket_config_ (client, socket_config_data_);
351 
352  TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint_));
353 
354  if (client_mon_) {
356  "inproc://client-monitor");
357  }
358 
359  return client;
360 }
361 
362 void expect_new_client_bounce_fail (char *my_endpoint_,
363  void *server_,
364  socket_config_fn socket_config_,
365  void *socket_config_data_,
366  void **client_mon_,
367  int expected_client_event_,
368  int expected_client_value_)
369 {
370  void *my_client_mon = NULL;
371  TEST_ASSERT_TRUE (client_mon_ == NULL || expected_client_event_ == 0);
372  if (expected_client_event_ != 0)
373  client_mon_ = &my_client_mon;
374  void *client = create_and_connect_client (my_endpoint_, socket_config_,
375  socket_config_data_, client_mon_);
376  expect_bounce_fail (server_, client);
377 
378  if (expected_client_event_ != 0) {
379  int events_received = 0;
380  events_received = expect_monitor_event_multiple (
381  my_client_mon, expected_client_event_, expected_client_value_, false);
382 
383  TEST_ASSERT_EQUAL_INT (1, events_received);
384 
385  test_context_socket_close (my_client_mon);
386  }
387 
389 }
socket_config_fn
void() socket_config_fn(void *, void *)
Definition: testutil_security.hpp:11
curve_client_data_t
Definition: testutil_security.hpp:35
TEST_ASSERT_EQUAL_STRING
#define TEST_ASSERT_EQUAL_STRING(expected, actual)
Definition: unity.h:235
data_
StringPiece data_
Definition: bytestream_unittest.cc:60
socket_config_null_client
void socket_config_null_client(void *server_, void *server_secret_)
Definition: testutil_security.cpp:9
zap_status_internal_error
@ zap_status_internal_error
Definition: testutil_security.hpp:53
setup_handshake_socket_monitor
static void setup_handshake_socket_monitor(void *server_, void **server_mon_, const char *monitor_endpoint_)
Definition: testutil_security.cpp:243
ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL
#define ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL
Definition: zmq.h:414
expect_new_client_bounce_fail
void expect_new_client_bounce_fail(char *my_endpoint_, void *server_, socket_config_fn socket_config_, void *socket_config_data_, void **client_mon_, int expected_client_event_, int expected_client_value_)
Definition: testutil_security.cpp:362
domain
const char domain[]
Definition: test_security_plain.cpp:74
ZMQ_EVENT_HANDSHAKE_FAILED_AUTH
#define ZMQ_EVENT_HANDSHAKE_FAILED_AUTH
Definition: zmq.h:423
zap_ok
@ zap_ok
Definition: testutil_security.hpp:50
ZMQ_PLAIN_USERNAME
#define ZMQ_PLAIN_USERNAME
Definition: zmq.h:310
NULL
NULL
Definition: test_security_zap.cpp:405
zmq_threadstart
ZMQ_EXPORT void * zmq_threadstart(zmq_thread_fn *func_, void *arg_)
Definition: zmq_utils.cpp:54
curve_client_data_t::client_public
const char * client_public
Definition: testutil_security.hpp:38
ZMQ_ZAP_ENFORCE_DOMAIN
#define ZMQ_ZAP_ENFORCE_DOMAIN
Definition: zmq_draft.h:25
setup_context_and_server_side
void setup_context_and_server_side(void **zap_control_, void **zap_thread_, void **server_, void **server_mon_, char *my_endpoint_, zmq_thread_fn zap_handler_, socket_config_fn socket_config_, void *socket_config_data_, const char *routing_id_)
Definition: testutil_security.cpp:264
zmq_unbind
ZMQ_EXPORT int zmq_unbind(void *s_, const char *addr_)
Definition: zmq.cpp:337
zmq_socket_monitor
ZMQ_EXPORT int zmq_socket_monitor(void *s_, const char *addr_, int events_)
Definition: zmq.cpp:278
TEST_ASSERT_TRUE
#define TEST_ASSERT_TRUE(condition)
Definition: unity.h:121
zmq_poll
ZMQ_EXPORT int zmq_poll(zmq_pollitem_t *items_, int nitems_, long timeout_)
Definition: zmq.cpp:827
ZMQ_PLAIN_SERVER
#define ZMQ_PLAIN_SERVER
Definition: zmq.h:309
ZMQ_CURVE_SECRETKEY
#define ZMQ_CURVE_SECRETKEY
Definition: zmq.h:314
zap_handler_generic
void zap_handler_generic(zap_protocol_t zap_protocol_, const char *expected_routing_id_)
Definition: testutil_security.cpp:98
zap_protocol_t
zap_protocol_t
Definition: testutil_security.hpp:48
testutil_security.hpp
zap_too_many_parts
@ zap_too_many_parts
Definition: testutil_security.hpp:58
curve_client_data_t::server_public
const char * server_public
Definition: testutil_security.hpp:37
ZMQ_PLAIN_PASSWORD
#define ZMQ_PLAIN_PASSWORD
Definition: zmq.h:311
ZMQ_CURVE_SERVERKEY
#define ZMQ_CURVE_SERVERKEY
Definition: zmq.h:315
zap_do_not_recv
@ zap_do_not_recv
Definition: testutil_security.hpp:60
bind_loopback_ipv4
void bind_loopback_ipv4(void *socket_, char *my_endpoint_, size_t len_)
Definition: testutil_unity.cpp:246
zmq_pollitem_t
Definition: zmq.h:487
get_test_context
void * get_test_context()
Definition: testutil_unity.cpp:184
client
void client(int num)
Definition: test_multithread.cpp:134
zap_wrong_request_id
@ zap_wrong_request_id
Definition: testutil_security.hpp:56
address
const char * address
Definition: builds/zos/test_fork.cpp:6
zmq_thread_fn
void() zmq_thread_fn(void *)
Definition: zmq.h:605
curve_client_data
static NULL curve_client_data_t curve_client_data
Definition: test_security_zap.cpp:407
test_context_socket_close_zero_linger
void * test_context_socket_close_zero_linger(void *socket_)
Definition: testutil_unity.cpp:215
close_zero_linger
void close_zero_linger(void *socket_)
Definition: testutil.cpp:193
TEST_FAIL_MESSAGE
#define TEST_FAIL_MESSAGE(message)
Definition: unity.h:101
s_recv
char * s_recv(void *socket_)
Definition: testutil.cpp:123
ZMQ_REQ
#define ZMQ_REQ
Definition: zmq.h:261
zmq_connect
ZMQ_EXPORT int zmq_connect(void *s_, const char *addr_)
Definition: zmq.cpp:307
ZMQ_POLLIN
#define ZMQ_POLLIN
Definition: zmq.h:482
zmq_atomic_counter_inc
ZMQ_EXPORT int zmq_atomic_counter_inc(void *counter_)
Definition: zmq_utils.cpp:271
valid_server_secret
char valid_server_secret[41]
Definition: testutil_security.cpp:55
ZMQ_EVENT_HANDSHAKE_SUCCEEDED
#define ZMQ_EVENT_HANDSHAKE_SUCCEEDED
Definition: zmq.h:417
ZMQ_DEALER
#define ZMQ_DEALER
Definition: zmq.h:263
socket_config_plain_server
void socket_config_plain_server(void *server_, void *server_secret_)
Definition: testutil_security.cpp:41
socket_config_plain_client
void socket_config_plain_client(void *server_, void *server_secret_)
Definition: testutil_security.cpp:31
zmq_z85_encode
ZMQ_EXPORT char * zmq_z85_encode(char *dest_, const uint8_t *data_, size_t size_)
Definition: zmq_utils.cpp:101
zmq_setsockopt
ZMQ_EXPORT int zmq_setsockopt(void *s_, int option_, const void *optval_, size_t optvallen_)
Definition: zmq.cpp:250
zmq_threadclose
ZMQ_EXPORT void zmq_threadclose(void *thread_)
Definition: zmq_utils.cpp:62
zmq_atomic_counter_new
ZMQ_EXPORT void * zmq_atomic_counter_new(void)
Definition: zmq_utils.cpp:255
socket_config_curve_server
void socket_config_curve_server(void *server_, void *server_secret_)
Definition: testutil_security.cpp:66
LIBZMQ_UNUSED
#define LIBZMQ_UNUSED(object)
Definition: macros.hpp:6
socket_config_null_server
void socket_config_null_server(void *server_, void *server_secret_)
Definition: testutil_security.cpp:15
ZMQ_REP
#define ZMQ_REP
Definition: zmq.h:262
valid_client_public
char valid_client_public[41]
Definition: testutil_security.cpp:52
test_zap_domain
const char * test_zap_domain
Definition: testutil_security.cpp:7
shutdown_context_and_server_side
void shutdown_context_and_server_side(void *zap_thread_, void *server_, void *server_mon_, void *zap_control_, bool zap_handler_stopped_)
Definition: testutil_security.cpp:314
MAX_SOCKET_STRING
#define MAX_SOCKET_STRING
Definition: libzmq/tests/testutil.hpp:35
zmq_bind
ZMQ_EXPORT int zmq_bind(void *s_, const char *addr_)
Definition: zmq.cpp:299
size
#define size
Definition: glcorearb.h:2944
zmq_socket
ZMQ_EXPORT void * zmq_socket(void *, int type_)
Definition: zmq.cpp:230
test_context_socket
void * test_context_socket(int type_)
Definition: testutil_unity.cpp:200
zap_do_not_send
@ zap_do_not_send
Definition: testutil_security.hpp:61
TEST_ASSERT_EQUAL_INT
#define TEST_ASSERT_EQUAL_INT(expected, actual)
Definition: unity.h:128
streq
bool streq(const char *lhs_, const char *rhs_)
Definition: testutil.cpp:508
zap_status_temporary_failure
@ zap_status_temporary_failure
Definition: testutil_security.hpp:52
ZMQ_ZAP_DOMAIN
#define ZMQ_ZAP_DOMAIN
Definition: zmq.h:320
zmq_curve_keypair
ZMQ_EXPORT int zmq_curve_keypair(char *z85_public_key_, char *z85_secret_key_)
Definition: zmq_utils.cpp:190
expect_bounce_fail
void expect_bounce_fail(void *server_, void *client_)
Definition: testutil.cpp:107
ZMQ_LINGER
#define ZMQ_LINGER
Definition: zmq.h:288
send_string_expect_success
void send_string_expect_success(void *socket_, const char *str_, int flags_)
Definition: testutil_unity.cpp:94
zap_handler
void zap_handler(void *)
Definition: testutil_security.cpp:238
ZMQ_PAIR
#define ZMQ_PAIR
Definition: zmq.h:258
zmq_recv
ZMQ_EXPORT int zmq_recv(void *s_, void *buf_, size_t len_, int flags_)
Definition: zmq.cpp:487
ZMQ_CURVE_SERVER
#define ZMQ_CURVE_SERVER
Definition: zmq.h:312
create_and_connect_client
void * create_and_connect_client(char *my_endpoint_, socket_config_fn socket_config_, void *socket_config_data_, void **client_mon_)
Definition: testutil_security.cpp:338
expect_monitor_event_multiple
int expect_monitor_event_multiple(void *server_mon_, int expected_event_, int expected_err_, bool optional_)
Definition: testutil_monitoring.cpp:127
test_plain_username
static const char test_plain_username[]
Definition: testutil_security.cpp:28
size
GLsizeiptr size
Definition: glcorearb.h:2943
recv_string_expect_success
void recv_string_expect_success(void *socket_, const char *str_, int flags_)
Definition: testutil_unity.cpp:101
valid_server_public
char valid_server_public[41]
Definition: testutil_security.cpp:54
valid_client_secret
char valid_client_secret[41]
Definition: testutil_security.cpp:53
ZMQ_SNDMORE
#define ZMQ_SNDMORE
Definition: zmq.h:359
ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL
#define ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL
Definition: zmq.h:420
zmq_atomic_counter_destroy
ZMQ_EXPORT void zmq_atomic_counter_destroy(void **counter_p_)
Definition: zmq_utils.cpp:293
ZMQ_ROUTING_ID
#define ZMQ_ROUTING_ID
Definition: zmq.h:277
socket_config_curve_client
void socket_config_curve_client(void *client_, void *data_)
Definition: testutil_security.cpp:83
handler
void * handler
Definition: test_security_curve.cpp:27
zap_status_invalid
@ zap_status_invalid
Definition: testutil_security.hpp:57
test_plain_password
static const char test_plain_password[]
Definition: testutil_security.cpp:29
ZMQ_MAXMSGSIZE
#define ZMQ_MAXMSGSIZE
Definition: zmq.h:292
curve_client_data_t::client_secret
const char * client_secret
Definition: testutil_security.hpp:39
version
static struct @0 version
test_context_socket_close
void * test_context_socket_close(void *socket_)
Definition: testutil_unity.cpp:208
TEST_ASSERT_NOT_NULL
#define TEST_ASSERT_NOT_NULL(pointer)
Definition: unity.h:125
zap_wrong_version
@ zap_wrong_version
Definition: testutil_security.hpp:55
TEST_ASSERT_SUCCESS_ERRNO
#define TEST_ASSERT_SUCCESS_ERRNO(expr)
Definition: proxy_thr.cpp:47
ZMQ_CURVE_PUBLICKEY
#define ZMQ_CURVE_PUBLICKEY
Definition: zmq.h:313
zap_disconnect
@ zap_disconnect
Definition: testutil_security.hpp:59
setup_testutil_security_curve
void setup_testutil_security_curve()
Definition: testutil_security.cpp:57
zap_requests_handled
void * zap_requests_handled
Definition: testutil_security.cpp:96


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:59