Coverage Report

Created: 2025-10-13 07:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libzmq/tests/testutil_security.cpp
Line
Count
Source
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
0
{
11
0
    LIBZMQ_UNUSED (server_);
12
0
    LIBZMQ_UNUSED (server_secret_);
13
0
}
14
15
void socket_config_null_server (void *server_, void *server_secret_)
16
0
{
17
0
    TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
18
0
      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;
21
    TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (server_, ZMQ_ZAP_ENFORCE_DOMAIN,
22
                                               &required, sizeof (int)));
23
#else
24
0
    LIBZMQ_UNUSED (server_secret_);
25
0
#endif
26
0
}
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
0
{
33
0
    LIBZMQ_UNUSED (server_secret_);
34
35
0
    TEST_ASSERT_SUCCESS_ERRNO (
36
0
      zmq_setsockopt (server_, ZMQ_PLAIN_PASSWORD, test_plain_password, 8));
37
0
    TEST_ASSERT_SUCCESS_ERRNO (
38
0
      zmq_setsockopt (server_, ZMQ_PLAIN_USERNAME, test_plain_username, 8));
39
0
}
40
41
void socket_config_plain_server (void *server_, void *server_secret_)
42
0
{
43
0
    LIBZMQ_UNUSED (server_secret_);
44
45
0
    int as_server = 1;
46
0
    TEST_ASSERT_SUCCESS_ERRNO (
47
0
      zmq_setsockopt (server_, ZMQ_PLAIN_SERVER, &as_server, sizeof (int)));
48
0
    TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
49
0
      server_, ZMQ_ZAP_DOMAIN, test_zap_domain, strlen (test_zap_domain)));
50
0
}
51
52
char valid_client_public[41];
53
char valid_client_secret[41];
54
char valid_server_public[41];
55
char valid_server_secret[41];
56
57
void setup_testutil_security_curve ()
58
0
{
59
    //  Generate new keypairs for these tests
60
0
    TEST_ASSERT_SUCCESS_ERRNO (
61
0
      zmq_curve_keypair (valid_client_public, valid_client_secret));
62
0
    TEST_ASSERT_SUCCESS_ERRNO (
63
0
      zmq_curve_keypair (valid_server_public, valid_server_secret));
64
0
}
65
66
void socket_config_curve_server (void *server_, void *server_secret_)
67
0
{
68
0
    int as_server = 1;
69
0
    TEST_ASSERT_SUCCESS_ERRNO (
70
0
      zmq_setsockopt (server_, ZMQ_CURVE_SERVER, &as_server, sizeof (int)));
71
0
    TEST_ASSERT_SUCCESS_ERRNO (
72
0
      zmq_setsockopt (server_, ZMQ_CURVE_SECRETKEY, server_secret_, 41));
73
0
    TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
74
0
      server_, ZMQ_ZAP_DOMAIN, test_zap_domain, strlen (test_zap_domain)));
75
76
#ifdef ZMQ_ZAP_ENFORCE_DOMAIN
77
    int required = 1;
78
    TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (server_, ZMQ_ZAP_ENFORCE_DOMAIN,
79
                                               &required, sizeof (int)));
80
#endif
81
0
}
82
83
void socket_config_curve_client (void *client_, void *data_)
84
0
{
85
0
    const curve_client_data_t *const curve_client_data =
86
0
      static_cast<const curve_client_data_t *> (data_);
87
88
0
    TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
89
0
      client_, ZMQ_CURVE_SERVERKEY, curve_client_data->server_public, 41));
90
0
    TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
91
0
      client_, ZMQ_CURVE_PUBLICKEY, curve_client_data->client_public, 41));
92
0
    TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
93
0
      client_, ZMQ_CURVE_SECRETKEY, curve_client_data->client_secret, 41));
94
0
}
95
96
void *zap_requests_handled;
97
98
void zap_handler_generic (zap_protocol_t zap_protocol_,
99
                          const char *expected_routing_id_)
100
0
{
101
0
    void *control = zmq_socket (get_test_context (), ZMQ_REQ);
102
0
    TEST_ASSERT_NOT_NULL (control);
103
0
    TEST_ASSERT_SUCCESS_ERRNO (
104
0
      zmq_connect (control, "inproc://handler-control"));
105
106
0
    void *handler = zmq_socket (get_test_context (), ZMQ_REP);
107
0
    TEST_ASSERT_NOT_NULL (handler);
108
0
    TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (handler, "inproc://zeromq.zap.01"));
109
110
    //  Signal main thread that we are ready
111
0
    send_string_expect_success (control, "GO", 0);
112
113
0
    zmq_pollitem_t items[] = {
114
0
      {control, 0, ZMQ_POLLIN, 0},
115
0
      {handler, 0, ZMQ_POLLIN, 0},
116
0
    };
117
118
    // if ordered not to receive the request, ignore the second poll item
119
0
    const int numitems = (zap_protocol_ == zap_do_not_recv) ? 1 : 2;
120
121
    //  Process ZAP requests forever
122
0
    while (zmq_poll (items, numitems, -1) >= 0) {
123
0
        if (items[0].revents & ZMQ_POLLIN) {
124
0
            recv_string_expect_success (control, "STOP", 0);
125
0
            break; //  Terminating - main thread signal
126
0
        }
127
0
        if (!(items[1].revents & ZMQ_POLLIN))
128
0
            continue;
129
130
0
        char *version = s_recv (handler);
131
0
        if (!version)
132
0
            break; //  Terminating - peer's socket closed
133
0
        if (zap_protocol_ == zap_disconnect) {
134
0
            free (version);
135
0
            break;
136
0
        }
137
138
0
        char *sequence = s_recv (handler);
139
0
        char *domain = s_recv (handler);
140
0
        char *address = s_recv (handler);
141
0
        char *routing_id = s_recv (handler);
142
0
        char *mechanism = s_recv (handler);
143
0
        bool authentication_succeeded = false;
144
0
        if (streq (mechanism, "CURVE")) {
145
0
            uint8_t client_key[32];
146
0
            TEST_ASSERT_EQUAL_INT (32, TEST_ASSERT_SUCCESS_ERRNO (zmq_recv (
147
0
                                         handler, client_key, 32, 0)));
148
149
0
            char client_key_text[41];
150
0
            zmq_z85_encode (client_key_text, client_key, 32);
151
152
0
            authentication_succeeded =
153
0
              streq (client_key_text, valid_client_public);
154
0
        } else if (streq (mechanism, "PLAIN")) {
155
0
            char client_username[32];
156
0
            int size = TEST_ASSERT_SUCCESS_ERRNO (
157
0
              zmq_recv (handler, client_username, 32, 0));
158
0
            client_username[size] = 0;
159
160
0
            char client_password[32];
161
0
            size = TEST_ASSERT_SUCCESS_ERRNO (
162
0
              zmq_recv (handler, client_password, 32, 0));
163
0
            client_password[size] = 0;
164
165
0
            authentication_succeeded =
166
0
              streq (test_plain_username, client_username)
167
0
              && streq (test_plain_password, client_password);
168
0
        } else if (streq (mechanism, "NULL")) {
169
0
            authentication_succeeded = true;
170
0
        } else {
171
0
            char msg[128];
172
0
            printf ("Unsupported mechanism: %s\n", mechanism);
173
0
            TEST_FAIL_MESSAGE (msg);
174
0
        }
175
176
0
        TEST_ASSERT_EQUAL_STRING ("1.0", version);
177
0
        TEST_ASSERT_EQUAL_STRING (expected_routing_id_, routing_id);
178
179
0
        send_string_expect_success (
180
0
          handler,
181
0
          zap_protocol_ == zap_wrong_version ? "invalid_version" : version,
182
0
          ZMQ_SNDMORE);
183
0
        send_string_expect_success (handler,
184
0
                                    zap_protocol_ == zap_wrong_request_id
185
0
                                      ? "invalid_request_id"
186
0
                                      : sequence,
187
0
                                    ZMQ_SNDMORE);
188
189
0
        if (authentication_succeeded) {
190
0
            const char *status_code;
191
0
            switch (zap_protocol_) {
192
0
                case zap_status_internal_error:
193
0
                    status_code = "500";
194
0
                    break;
195
0
                case zap_status_temporary_failure:
196
0
                    status_code = "300";
197
0
                    break;
198
0
                case zap_status_invalid:
199
0
                    status_code = "invalid_status";
200
0
                    break;
201
0
                default:
202
0
                    status_code = "200";
203
0
            }
204
0
            send_string_expect_success (handler, status_code, ZMQ_SNDMORE);
205
0
            send_string_expect_success (handler, "OK", ZMQ_SNDMORE);
206
0
            send_string_expect_success (handler, "anonymous", ZMQ_SNDMORE);
207
0
            if (zap_protocol_ == zap_too_many_parts) {
208
0
                send_string_expect_success (handler, "", ZMQ_SNDMORE);
209
0
            }
210
0
            if (zap_protocol_ != zap_do_not_send)
211
0
                send_string_expect_success (handler, "", 0);
212
0
        } else {
213
0
            send_string_expect_success (handler, "400", ZMQ_SNDMORE);
214
0
            send_string_expect_success (handler, "Invalid client public key",
215
0
                                        ZMQ_SNDMORE);
216
0
            send_string_expect_success (handler, "", ZMQ_SNDMORE);
217
0
            if (zap_protocol_ != zap_do_not_send)
218
0
                send_string_expect_success (handler, "", 0);
219
0
        }
220
0
        free (version);
221
0
        free (sequence);
222
0
        free (domain);
223
0
        free (address);
224
0
        free (routing_id);
225
0
        free (mechanism);
226
227
0
        zmq_atomic_counter_inc (zap_requests_handled);
228
0
    }
229
0
    TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (handler, "inproc://zeromq.zap.01"));
230
0
    close_zero_linger (handler);
231
232
0
    if (zap_protocol_ != zap_disconnect) {
233
0
        send_string_expect_success (control, "STOPPED", 0);
234
0
    }
235
0
    close_zero_linger (control);
236
0
}
237
238
void zap_handler (void *)
239
0
{
240
0
    zap_handler_generic (zap_ok);
241
0
}
242
243
static void setup_handshake_socket_monitor (void *server_,
244
                                            void **server_mon_,
245
                                            const char *monitor_endpoint_)
246
0
{
247
    //  Monitor handshake events on the server
248
0
    TEST_ASSERT_SUCCESS_ERRNO (zmq_socket_monitor (
249
0
      server_, monitor_endpoint_,
250
0
      ZMQ_EVENT_HANDSHAKE_SUCCEEDED | ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL
251
0
        | ZMQ_EVENT_HANDSHAKE_FAILED_AUTH
252
0
        | ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL));
253
254
    //  Create socket for collecting monitor events
255
0
    *server_mon_ = test_context_socket (ZMQ_PAIR);
256
0
    int linger = 0;
257
0
    TEST_ASSERT_SUCCESS_ERRNO (
258
0
      zmq_setsockopt (*server_mon_, ZMQ_LINGER, &linger, sizeof (linger)));
259
260
    //  Connect it to the inproc endpoints so they'll get events
261
0
    TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (*server_mon_, monitor_endpoint_));
262
0
}
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
0
{
274
    //  Spawn ZAP handler
275
0
    zap_requests_handled = zmq_atomic_counter_new ();
276
0
    TEST_ASSERT_NOT_NULL (zap_requests_handled);
277
278
0
    *zap_control_ = test_context_socket (ZMQ_REP);
279
0
    TEST_ASSERT_SUCCESS_ERRNO (
280
0
      zmq_bind (*zap_control_, "inproc://handler-control"));
281
0
    int linger = 0;
282
0
    TEST_ASSERT_SUCCESS_ERRNO (
283
0
      zmq_setsockopt (*zap_control_, ZMQ_LINGER, &linger, sizeof (linger)));
284
285
0
    if (zap_handler_ != NULL) {
286
0
        *zap_thread_ = zmq_threadstart (zap_handler_, NULL);
287
288
0
        recv_string_expect_success (*zap_control_, "GO", 0);
289
0
    } else
290
0
        *zap_thread_ = NULL;
291
292
    //  Server socket will accept connections
293
0
    *server_ = test_context_socket (ZMQ_DEALER);
294
0
    TEST_ASSERT_SUCCESS_ERRNO (
295
0
      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
0
    int64_t max_msg_size = 64 * 1024 * 1024;
299
0
    TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
300
0
      *server_, ZMQ_MAXMSGSIZE, &max_msg_size, sizeof (int64_t)));
301
302
0
    socket_config_ (*server_, socket_config_data_);
303
304
0
    TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
305
0
      *server_, ZMQ_ROUTING_ID, routing_id_, strlen (routing_id_)));
306
307
0
    bind_loopback_ipv4 (*server_, my_endpoint_, MAX_SOCKET_STRING);
308
309
0
    const char server_monitor_endpoint[] = "inproc://monitor-server";
310
0
    setup_handshake_socket_monitor (*server_, server_mon_,
311
0
                                    server_monitor_endpoint);
312
0
}
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
0
{
320
0
    if (zap_thread_ && !zap_handler_stopped_) {
321
0
        send_string_expect_success (zap_control_, "STOP", 0);
322
0
        recv_string_expect_success (zap_control_, "STOPPED", 0);
323
0
        TEST_ASSERT_SUCCESS_ERRNO (
324
0
          zmq_unbind (zap_control_, "inproc://handler-control"));
325
0
    }
326
0
    test_context_socket_close (zap_control_);
327
0
    zmq_socket_monitor (server_, NULL, 0);
328
0
    test_context_socket_close (server_mon_);
329
0
    test_context_socket_close (server_);
330
331
    //  Wait until ZAP handler terminates
332
0
    if (zap_thread_)
333
0
        zmq_threadclose (zap_thread_);
334
335
0
    zmq_atomic_counter_destroy (&zap_requests_handled);
336
0
}
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
0
{
343
0
    void *client = test_context_socket (ZMQ_DEALER);
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
0
    int64_t max_msg_size = 64 * 1024 * 1024;
347
0
    TEST_ASSERT_SUCCESS_ERRNO (
348
0
      zmq_setsockopt (client, ZMQ_MAXMSGSIZE, &max_msg_size, sizeof (int64_t)));
349
350
0
    socket_config_ (client, socket_config_data_);
351
352
0
    TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint_));
353
354
0
    if (client_mon_) {
355
0
        setup_handshake_socket_monitor (client, client_mon_,
356
0
                                        "inproc://client-monitor");
357
0
    }
358
359
0
    return client;
360
0
}
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
0
{
370
0
    void *my_client_mon = NULL;
371
0
    TEST_ASSERT_TRUE (client_mon_ == NULL || expected_client_event_ == 0);
372
0
    if (expected_client_event_ != 0)
373
0
        client_mon_ = &my_client_mon;
374
0
    void *client = create_and_connect_client (my_endpoint_, socket_config_,
375
0
                                              socket_config_data_, client_mon_);
376
0
    expect_bounce_fail (server_, client);
377
378
0
    if (expected_client_event_ != 0) {
379
0
        int events_received = 0;
380
0
        events_received = expect_monitor_event_multiple (
381
0
          my_client_mon, expected_client_event_, expected_client_value_, false);
382
383
0
        TEST_ASSERT_EQUAL_INT (1, events_received);
384
385
0
        test_context_socket_close (my_client_mon);
386
0
    }
387
388
0
    test_context_socket_close_zero_linger (client);
389
0
}