test_security_curve.cpp 21.8 KB
Newer Older
Ian Barber's avatar
Ian Barber committed
1
/*
2
    Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
Ian Barber's avatar
Ian Barber committed
3

4
    This file is part of libzmq, the ZeroMQ core engine in C++.
Ian Barber's avatar
Ian Barber committed
5

6 7 8
    libzmq is free software; you can redistribute it and/or modify it under
    the terms of the GNU Lesser General Public License (LGPL) as published
    by the Free Software Foundation; either version 3 of the License, or
Ian Barber's avatar
Ian Barber committed
9 10
    (at your option) any later version.

11 12 13 14 15 16 17 18 19 20 21 22 23 24
    As a special exception, the Contributors give you permission to link
    this library with independent modules to produce an executable,
    regardless of the license terms of these independent modules, and to
    copy and distribute the resulting executable under terms of your choice,
    provided that you also meet, for each linked independent module, the
    terms and conditions of the license of that module. An independent
    module is a module which is not derived from or based on this library.
    If you modify this library, you must extend this exception to your
    version of the library.

    libzmq is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
    License for more details.
Ian Barber's avatar
Ian Barber committed
25 26 27 28 29 30

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "testutil.hpp"
31
#include "testutil_security.hpp"
32 33 34 35 36
#if defined(ZMQ_HAVE_WINDOWS)
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdexcept>
#define close closesocket
37
#else
38 39 40 41
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
42
#endif
43
#include <unity.h>
44

45 46 47 48
#include "../src/tweetnacl.h"
#include "../src/curve_client_tools.hpp"
#include "../src/random.hpp"

49 50
char error_message_buffer[256];

51 52 53 54
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf
#endif

55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
const char *zmq_errno_message ()
{
    snprintf (error_message_buffer, sizeof (error_message_buffer),
              "errno=%i (%s)", zmq_errno (), zmq_strerror (zmq_errno ()));
    return error_message_buffer;
}

#define TEST_ASSERT_ZMQ_ERRNO(condition)                                       \
    TEST_ASSERT_MESSAGE ((condition), zmq_errno_message ())

void *ctx;
void *handler;
void *zap_thread;
void *server;
void *server_mon;
char my_endpoint[MAX_SOCKET_STRING];

void setUp ()
{
    setup_context_and_server_side (&ctx, &handler, &zap_thread, &server,
                                   &server_mon, my_endpoint);
}

void tearDown ()
{
    shutdown_context_and_server_side (ctx, zap_thread, server, server_mon,
                                      handler);
}

const int timeout = 250;

86
const char large_routing_id[] = "0123456789012345678901234567890123456789"
87 88 89 90 91 92
                                "0123456789012345678901234567890123456789"
                                "0123456789012345678901234567890123456789"
                                "0123456789012345678901234567890123456789"
                                "0123456789012345678901234567890123456789"
                                "0123456789012345678901234567890123456789"
                                "012345678901234";
93

94
static void zap_handler_large_routing_id (void *ctx_)
95
{
96
    zap_handler_generic (ctx_, zap_ok, large_routing_id);
97 98
}

99 100 101 102 103 104 105 106 107 108 109 110
void expect_new_client_curve_bounce_fail (void *ctx_,
                                          char *server_public_,
                                          char *client_public_,
                                          char *client_secret_,
                                          char *my_endpoint_,
                                          void *server_,
                                          void **client_mon_ = NULL,
                                          int expected_client_event_ = 0,
                                          int expected_client_value_ = 0)
{
    curve_client_data_t curve_client_data = {server_public_, client_public_,
                                             client_secret_};
111
    expect_new_client_bounce_fail (
112 113 114
      ctx_, my_endpoint_, server_, socket_config_curve_client,
      &curve_client_data, client_mon_, expected_client_event_,
      expected_client_value_);
115 116
}

117 118 119 120 121 122 123
void test_null_key (void *ctx_,
                    void *server_,
                    void *server_mon_,
                    char *my_endpoint_,
                    char *server_public_,
                    char *client_public_,
                    char *client_secret_)
124
{
125 126
    expect_new_client_curve_bounce_fail (ctx_, server_public_, client_public_,
                                         client_secret_, my_endpoint_, server_);
127

128
#ifdef ZMQ_BUILD_DRAFT_API
129
    int handshake_failed_encryption_event_count =
130
      expect_monitor_event_multiple (server_mon_,
131 132
                                     ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
                                     ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC);
133

134
    // handshake_failed_encryption_event_count should be at least two because
135
    // expect_bounce_fail involves two exchanges
136 137
    // however, with valgrind we see only one event (maybe the next one takes
    // very long, or does not happen at all because something else takes very
138
    // long)
139 140

    fprintf (stderr,
141 142 143
             "count of "
             "ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL/"
             "ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC events: %i\n",
144
             handshake_failed_encryption_event_count);
145 146 147
#endif
}

148
void test_curve_security_with_valid_credentials ()
149
{
150 151
    curve_client_data_t curve_client_data = {
      valid_server_public, valid_client_public, valid_client_secret};
152 153 154 155
    void *client_mon;
    void *client =
      create_and_connect_client (ctx, my_endpoint, socket_config_curve_client,
                                 &curve_client_data, &client_mon);
156
    bounce (server, client);
157
    int rc = zmq_close (client);
158
    TEST_ASSERT_ZMQ_ERRNO (rc == 0);
159

160
#ifdef ZMQ_BUILD_DRAFT_API
161
    int event = get_monitor_event_with_timeout (server_mon, NULL, NULL, -1);
162 163 164
    assert (event == ZMQ_EVENT_HANDSHAKE_SUCCEEDED);

    assert_no_more_monitor_events_with_timeout (server_mon, timeout);
165 166 167 168 169 170 171

    event = get_monitor_event_with_timeout (client_mon, NULL, NULL, -1);
    assert (event == ZMQ_EVENT_HANDSHAKE_SUCCEEDED);

    assert_no_more_monitor_events_with_timeout (client_mon, timeout);

    rc = zmq_close (client_mon);
172
    TEST_ASSERT_ZMQ_ERRNO (rc == 0);
173
#endif
174
}
175

176
void test_curve_security_with_bogus_client_credentials ()
177
{
178
    //  This must be caught by the ZAP handler
179 180
    char bogus_public[41];
    char bogus_secret[41];
181
    zmq_curve_keypair (bogus_public, bogus_secret);
182

183
    expect_new_client_curve_bounce_fail (ctx, valid_server_public, bogus_public,
184
                                         bogus_secret, my_endpoint, server,
185 186 187 188 189 190 191
                                         NULL,
#ifdef ZMQ_BUILD_DRAFT_API
                                         ZMQ_EVENT_HANDSHAKE_FAILED_AUTH, 400
#else
                                         0, 0
#endif
    );
192

193
    int server_event_count = 0;
194
#ifdef ZMQ_BUILD_DRAFT_API
195
    server_event_count = expect_monitor_event_multiple (
196
      server_mon, ZMQ_EVENT_HANDSHAKE_FAILED_AUTH, 400);
197
    TEST_ASSERT_LESS_OR_EQUAL_INT (1, server_event_count);
198
#endif
199 200

    // there may be more than one ZAP request due to repeated attempts by the client
201 202
    TEST_ASSERT (0 == server_event_count
                 || 1 <= zmq_atomic_counter_value (zap_requests_handled));
203
}
204

205 206 207 208
void expect_zmtp_mechanism_mismatch (void *client_,
                                     char *my_endpoint_,
                                     void *server_,
                                     void *server_mon_)
209
{
210
    //  This must be caught by the curve_server class, not passed to ZAP
211
    int rc = zmq_connect (client_, my_endpoint_);
212
    TEST_ASSERT_ZMQ_ERRNO (rc == 0);
213 214
    expect_bounce_fail (server_, client_);
    close_zero_linger (client_);
215

216
#ifdef ZMQ_BUILD_DRAFT_API
217
    expect_monitor_event_multiple (server_mon_,
218 219
                                   ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
                                   ZMQ_PROTOCOL_ERROR_ZMTP_MECHANISM_MISMATCH);
220
#endif
221

222
    TEST_ASSERT_EQUAL_INT (0, zmq_atomic_counter_value (zap_requests_handled));
223
}
224

225
void test_curve_security_with_null_client_credentials ()
226 227
{
    void *client = zmq_socket (ctx, ZMQ_DEALER);
228
    TEST_ASSERT_NOT_NULL (client);
229

230
    expect_zmtp_mechanism_mismatch (client, my_endpoint, server, server_mon);
231 232
}

233
void test_curve_security_with_plain_client_credentials ()
234 235
{
    void *client = zmq_socket (ctx, ZMQ_DEALER);
236
    TEST_ASSERT_NOT_NULL (client);
237
    int rc = zmq_setsockopt (client, ZMQ_PLAIN_USERNAME, "admin", 5);
238
    TEST_ASSERT_ZMQ_ERRNO (rc == 0);
239
    rc = zmq_setsockopt (client, ZMQ_PLAIN_PASSWORD, "password", 8);
240
    TEST_ASSERT_ZMQ_ERRNO (rc == 0);
241

242
    expect_zmtp_mechanism_mismatch (client, my_endpoint, server, server_mon);
243
}
244

245
fd_t connect_vanilla_socket (char *my_endpoint_)
246
{
247
    fd_t s;
248
    struct sockaddr_in ip4addr;
249

250
    unsigned short int port;
251
    int rc = sscanf (my_endpoint_, "tcp://127.0.0.1:%hu", &port);
252
    TEST_ASSERT_EQUAL_INT (1, rc);
253

254
    ip4addr.sin_family = AF_INET;
255
    ip4addr.sin_port = htons (port);
256
#if defined(ZMQ_HAVE_WINDOWS) && (_WIN32_WINNT < 0x0600)
257 258
    ip4addr.sin_addr.s_addr = inet_addr ("127.0.0.1");
#else
259
    inet_pton (AF_INET, "127.0.0.1", &ip4addr.sin_addr);
260
#endif
261 262

    s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
263
    rc = connect (s, (struct sockaddr *) &ip4addr, sizeof (ip4addr));
264
    TEST_ASSERT_GREATER_THAN_INT (-1, rc);
265 266 267
    return s;
}

268
void test_curve_security_unauthenticated_message ()
269 270
{
    // Unauthenticated messages from a vanilla socket shouldn't be received
271
    fd_t s = connect_vanilla_socket (my_endpoint);
272 273 274 275
    // send anonymous ZMTP/1.0 greeting
    send (s, "\x01\x00", 2, 0);
    // send sneaky message that shouldn't be received
    send (s, "\x08\x00sneaky\0", 9, 0);
276

277 278
    zmq_setsockopt (server, ZMQ_RCVTIMEO, &timeout, sizeof (timeout));
    char *buf = s_recv (server);
279
    TEST_ASSERT_NULL_MESSAGE (buf, "Received unauthenticated message");
280
    close (s);
281
}
282

283
void send_all (fd_t fd_, const char *data_, socket_size_t size_)
284
{
285 286
    while (size_ > 0) {
        int res = send (fd_, data_, size_, 0);
287
        TEST_ASSERT_GREATER_THAN_INT (0, res);
288 289
        size_ -= res;
        data_ += res;
290 291 292
    }
}

293
template <size_t N> void send (fd_t fd_, const char (&data_)[N])
294
{
295
    send_all (fd_, data_, N - 1);
296 297
}

298
void send_greeting (fd_t s_)
299
{
300 301 302 303 304
    send (s_, "\xff\0\0\0\0\0\0\0\0\x7f");            // signature
    send (s_, "\x03\x00");                            // version 3.0
    send (s_, "CURVE\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); // mechanism CURVE
    send (s_, "\0");                                  // as-server == false
    send (s_, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
305 306
}

307
void test_curve_security_invalid_hello_wrong_length ()
308
{
309
    fd_t s = connect_vanilla_socket (my_endpoint);
310 311 312 313 314

    // send GREETING
    send_greeting (s);

    // send CURVE HELLO of wrong size
315
    send (s, "\x04\x06\x05HELLO");
316 317

#ifdef ZMQ_BUILD_DRAFT_API
318 319 320
    expect_monitor_event_multiple (
      server_mon, ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
      ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_HELLO);
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
#endif

    close (s);
}

const size_t hello_length = 200;
const size_t welcome_length = 168;

zmq::curve_client_tools_t make_curve_client_tools ()
{
    uint8_t valid_client_secret_decoded[32];
    uint8_t valid_client_public_decoded[32];

    zmq_z85_decode (valid_client_public_decoded, valid_client_public);
    zmq_z85_decode (valid_client_secret_decoded, valid_client_secret);

    uint8_t valid_server_public_decoded[32];
    zmq_z85_decode (valid_server_public_decoded, valid_server_public);

    return zmq::curve_client_tools_t (valid_client_public_decoded,
                                      valid_client_secret_decoded,
                                      valid_server_public_decoded);
}

#ifndef htonll
346
uint64_t htonll (uint64_t value_)
347 348 349 350 351 352
{
    // The answer is 42
    static const int num = 42;

    // Check the endianness
    if (*reinterpret_cast<const char *> (&num) == num) {
353
        const uint32_t high_part = htonl (static_cast<uint32_t> (value_ >> 32));
354
        const uint32_t low_part =
355
          htonl (static_cast<uint32_t> (value_ & 0xFFFFFFFFLL));
356 357 358

        return (static_cast<uint64_t> (low_part) << 32) | high_part;
    } else {
359
        return value_;
360 361 362 363
    }
}
#endif

364
template <size_t N> void send_command (fd_t s_, char (&command_)[N])
365
{
366
    if (N < 256) {
367
        send (s_, "\x04");
368
        char len = (char) N;
369
        send_all (s_, &len, 1);
370
    } else {
371
        send (s_, "\x06");
372
        uint64_t len = htonll (N);
373
        send_all (s_, (char *) &len, 8);
374
    }
375
    send_all (s_, command_, N);
376 377
}

378
void test_curve_security_invalid_hello_command_name ()
379
{
380
    fd_t s = connect_vanilla_socket (my_endpoint);
381 382 383 384 385 386 387 388

    send_greeting (s);

    zmq::curve_client_tools_t tools = make_curve_client_tools ();

    // send CURVE HELLO with a misspelled command name (but otherwise correct)
    char hello[hello_length];
    int rc = tools.produce_hello (hello, 0);
389
    TEST_ASSERT_ZMQ_ERRNO (rc == 0);
390 391
    hello[5] = 'X';

392
    send_command (s, hello);
393 394

#ifdef ZMQ_BUILD_DRAFT_API
395 396 397
    expect_monitor_event_multiple (server_mon,
                                   ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
                                   ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND);
398 399 400 401 402
#endif

    close (s);
}

403
void test_curve_security_invalid_hello_version ()
404
{
405
    fd_t s = connect_vanilla_socket (my_endpoint);
406 407 408 409 410 411 412 413

    send_greeting (s);

    zmq::curve_client_tools_t tools = make_curve_client_tools ();

    // send CURVE HELLO with a wrong version number (but otherwise correct)
    char hello[hello_length];
    int rc = tools.produce_hello (hello, 0);
414
    TEST_ASSERT_ZMQ_ERRNO (rc == 0);
415 416 417 418 419
    hello[6] = 2;

    send_command (s, hello);

#ifdef ZMQ_BUILD_DRAFT_API
420 421 422
    expect_monitor_event_multiple (
      server_mon, ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
      ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_HELLO);
423 424 425 426 427
#endif

    close (s);
}

428
void flush_read (fd_t fd_)
429 430 431 432
{
    int res;
    char buf[256];

433
    while ((res = recv (fd_, buf, 256, 0)) == 256) {
434
    }
435
    TEST_ASSERT_NOT_EQUAL (-1, res);
436 437
}

438
void recv_all (fd_t fd_, uint8_t *data_, socket_size_t len_)
439
{
440
    socket_size_t received = 0;
441 442
    while (received < len_) {
        int res = recv (fd_, (char *) data_, len_, 0);
443
        TEST_ASSERT_GREATER_THAN_INT (0, res);
444

445
        data_ += res;
446 447
        received += res;
    }
448 449
}

450
void recv_greeting (fd_t fd_)
451 452
{
    uint8_t greeting[64];
453
    recv_all (fd_, greeting, 64);
454 455 456
    //  TODO assert anything about the greeting received from the server?
}

457 458
fd_t connect_exchange_greeting_and_send_hello (
  char *my_endpoint_, zmq::curve_client_tools_t &tools_)
459
{
460
    fd_t s = connect_vanilla_socket (my_endpoint_);
461 462 463 464 465 466

    send_greeting (s);
    recv_greeting (s);

    // send valid CURVE HELLO
    char hello[hello_length];
467
    int rc = tools_.produce_hello (hello, 0);
468
    TEST_ASSERT_ZMQ_ERRNO (rc == 0);
469 470 471 472 473

    send_command (s, hello);
    return s;
}

474
void test_curve_security_invalid_initiate_wrong_length ()
475 476 477
{
    zmq::curve_client_tools_t tools = make_curve_client_tools ();

478
    fd_t s = connect_exchange_greeting_and_send_hello (my_endpoint, tools);
479 480 481 482 483 484

    // receive but ignore WELCOME
    flush_read (s);

#ifdef ZMQ_BUILD_DRAFT_API
    int res = get_monitor_event_with_timeout (server_mon, NULL, NULL, timeout);
485
    TEST_ASSERT_EQUAL_INT (-1, res);
486 487
#else
    LIBZMQ_UNUSED (timeout);
488 489
#endif

490
    send (s, "\x04\x09\x08INITIATE");
491 492

#ifdef ZMQ_BUILD_DRAFT_API
493 494 495
    expect_monitor_event_multiple (
      server_mon, ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
      ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_INITIATE);
496 497 498 499 500
#endif

    close (s);
}

501
fd_t connect_exchange_greeting_and_hello_welcome (
502 503 504 505
  char *my_endpoint_,
  void *server_mon_,
  int timeout_,
  zmq::curve_client_tools_t &tools_)
506
{
507
    fd_t s = connect_exchange_greeting_and_send_hello (my_endpoint_, tools_);
508 509 510 511

    // receive but ignore WELCOME
    uint8_t welcome[welcome_length + 2];
    recv_all (s, welcome, welcome_length + 2);
512 513

    uint8_t cn_precom[crypto_box_BEFORENMBYTES];
514
    int res = tools_.process_welcome (welcome + 2, welcome_length, cn_precom);
515
    TEST_ASSERT_ZMQ_ERRNO (res == 0);
516 517

#ifdef ZMQ_BUILD_DRAFT_API
518
    res = get_monitor_event_with_timeout (server_mon_, NULL, NULL, timeout_);
519
    TEST_ASSERT_EQUAL_INT (-1, res);
520 521 522 523 524
#endif

    return s;
}

525
void test_curve_security_invalid_initiate_command_name ()
526 527
{
    zmq::curve_client_tools_t tools = make_curve_client_tools ();
528
    fd_t s = connect_exchange_greeting_and_hello_welcome (
529 530
      my_endpoint, server_mon, timeout, tools);

531
    char initiate[257];
532 533 534 535 536 537 538
    tools.produce_initiate (initiate, 257, 1, NULL, 0);
    // modify command name
    initiate[5] = 'X';

    send_command (s, initiate);

#ifdef ZMQ_BUILD_DRAFT_API
539 540 541
    expect_monitor_event_multiple (server_mon,
                                   ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
                                   ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND);
542 543 544 545 546
#endif

    close (s);
}

547
void test_curve_security_invalid_initiate_command_encrypted_cookie ()
548 549
{
    zmq::curve_client_tools_t tools = make_curve_client_tools ();
550
    fd_t s = connect_exchange_greeting_and_hello_welcome (
551 552
      my_endpoint, server_mon, timeout, tools);

553
    char initiate[257];
554 555 556 557 558 559 560
    tools.produce_initiate (initiate, 257, 1, NULL, 0);
    // make garbage from encrypted cookie
    initiate[30] = !initiate[30];

    send_command (s, initiate);

#ifdef ZMQ_BUILD_DRAFT_API
561 562 563
    expect_monitor_event_multiple (server_mon,
                                   ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
                                   ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC);
564 565 566 567 568
#endif

    close (s);
}

569
void test_curve_security_invalid_initiate_command_encrypted_content ()
570 571
{
    zmq::curve_client_tools_t tools = make_curve_client_tools ();
572
    fd_t s = connect_exchange_greeting_and_hello_welcome (
573 574
      my_endpoint, server_mon, timeout, tools);

575
    char initiate[257];
576 577 578 579 580 581 582
    tools.produce_initiate (initiate, 257, 1, NULL, 0);
    // make garbage from encrypted content
    initiate[150] = !initiate[150];

    send_command (s, initiate);

#ifdef ZMQ_BUILD_DRAFT_API
583 584 585
    expect_monitor_event_multiple (server_mon,
                                   ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
                                   ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC);
586 587 588 589 590
#endif

    close (s);
}

591
void test_curve_security_invalid_keysize (void *ctx_)
592
{
593
    //  Check return codes for invalid buffer sizes
594
    void *client = zmq_socket (ctx_, ZMQ_DEALER);
595
    TEST_ASSERT_NOT_NULL (client);
596
    errno = 0;
597 598
    int rc =
      zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, valid_server_public, 123);
599 600
    assert (rc == -1 && errno == EINVAL);
    errno = 0;
601
    rc = zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, valid_client_public, 123);
602 603
    assert (rc == -1 && errno == EINVAL);
    errno = 0;
604
    rc = zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, valid_client_secret, 123);
605 606
    assert (rc == -1 && errno == EINVAL);
    rc = zmq_close (client);
607
    TEST_ASSERT_ZMQ_ERRNO (rc == 0);
608
}
609

610 611
// TODO why isn't this const?
char null_key[] = "0000000000000000000000000000000000000000";
612

613 614
void test_null_server_key ()
{
615
    //  Check CURVE security with a null server key
616
    //  This will be caught by the curve_server class, not passed to ZAP
617
    test_null_key (ctx, server, server_mon, my_endpoint, null_key,
618
                   valid_client_public, valid_client_secret);
619
}
620

621 622
void test_null_client_public_key ()
{
623
    //  Check CURVE security with a null client public key
624
    //  This will be caught by the curve_server class, not passed to ZAP
625
    test_null_key (ctx, server, server_mon, my_endpoint, valid_server_public,
626
                   null_key, valid_client_secret);
627
}
628

629 630 631
void test_null_client_secret_key ()
{
    //  Check CURVE security with a null client public key
632
    //  This will be caught by the curve_server class, not passed to ZAP
633
    test_null_key (ctx, server, server_mon, my_endpoint, valid_server_public,
634
                   valid_client_public, null_key);
635
}
636

637

638 639 640 641 642 643
int main (void)
{
    if (!zmq_has ("curve")) {
        printf ("CURVE encryption not installed, skipping test\n");
        return 0;
    }
644

645
    zmq::random_open ();
646

647
    setup_testutil_security_curve ();
648 649


650
    setup_test_environment ();
651

652 653 654 655 656 657 658 659 660
    UNITY_BEGIN ();
    RUN_TEST (test_curve_security_with_valid_credentials);
    RUN_TEST (test_null_server_key);
    RUN_TEST (test_null_client_public_key);
    RUN_TEST (test_null_client_secret_key);
    RUN_TEST (test_curve_security_with_bogus_client_credentials);
    RUN_TEST (test_curve_security_with_null_client_credentials);
    RUN_TEST (test_curve_security_with_plain_client_credentials);
    RUN_TEST (test_curve_security_unauthenticated_message);
661

662 663 664 665 666 667 668 669 670 671
    //  tests with misbehaving CURVE client
    RUN_TEST (test_curve_security_invalid_hello_wrong_length);
    RUN_TEST (test_curve_security_invalid_hello_command_name);
    RUN_TEST (test_curve_security_invalid_hello_version);
    RUN_TEST (test_curve_security_invalid_initiate_wrong_length);
    RUN_TEST (test_curve_security_invalid_initiate_command_name);
    RUN_TEST (test_curve_security_invalid_initiate_command_encrypted_cookie);
    RUN_TEST (test_curve_security_invalid_initiate_command_encrypted_content);

    // TODO this requires a deviating test setup, must be moved to a separate executable/fixture
672
    //  test with a large routing id (resulting in large metadata)
673
    fprintf (stderr,
674
             "test_curve_security_with_valid_credentials (large routing id)\n");
675 676
    setup_context_and_server_side (
      &ctx, &handler, &zap_thread, &server, &server_mon, my_endpoint,
677 678
      &zap_handler_large_routing_id, &socket_config_curve_server,
      &valid_server_secret, large_routing_id);
679
    test_curve_security_with_valid_credentials ();
680
    shutdown_context_and_server_side (ctx, zap_thread, server, server_mon,
681
                                      handler);
682

683 684
    ctx = zmq_ctx_new ();
    test_curve_security_invalid_keysize (ctx);
685
    int rc = zmq_ctx_term (ctx);
686
    TEST_ASSERT_ZMQ_ERRNO (rc == 0);
Ian Barber's avatar
Ian Barber committed
687

688 689
    zmq::random_close ();

690
    return UNITY_END ();
Ian Barber's avatar
Ian Barber committed
691
}