2013-06-22 16:17:25 +01:00
|
|
|
/*
|
2017-05-01 12:11:11 +01:00
|
|
|
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
|
2013-06-22 16:17:25 +01:00
|
|
|
|
2015-06-02 22:33:55 +02:00
|
|
|
This file is part of libzmq, the ZeroMQ core engine in C++.
|
2013-06-22 16:17:25 +01:00
|
|
|
|
2015-06-02 22:33:55 +02:00
|
|
|
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
|
2013-06-22 16:17:25 +01:00
|
|
|
(at your option) any later version.
|
|
|
|
|
2015-06-02 22:33:55 +02:00
|
|
|
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.
|
2013-06-22 16:17:25 +01:00
|
|
|
|
|
|
|
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"
|
2017-08-17 11:45:18 +02:00
|
|
|
#include "testutil_security.hpp"
|
2018-02-01 11:46:09 +01:00
|
|
|
#if defined(ZMQ_HAVE_WINDOWS)
|
|
|
|
#include <winsock2.h>
|
|
|
|
#include <ws2tcpip.h>
|
|
|
|
#include <stdexcept>
|
|
|
|
#define close closesocket
|
2014-12-03 10:34:34 -08:00
|
|
|
#else
|
2018-02-01 11:46:09 +01:00
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <unistd.h>
|
2014-12-03 10:34:34 -08:00
|
|
|
#endif
|
2018-02-04 16:23:21 +01:00
|
|
|
#include <unity.h>
|
2013-09-02 18:21:36 +02:00
|
|
|
|
2017-08-15 16:28:24 +02:00
|
|
|
#include "../src/tweetnacl.h"
|
|
|
|
#include "../src/curve_client_tools.hpp"
|
|
|
|
#include "../src/random.hpp"
|
|
|
|
|
2018-02-04 16:23:21 +01:00
|
|
|
char error_message_buffer[256];
|
|
|
|
|
2018-02-11 14:33:48 +01:00
|
|
|
#if defined(_MSC_VER) && _MSC_VER < 1900
|
|
|
|
#define snprintf _snprintf
|
|
|
|
#endif
|
|
|
|
|
2018-02-04 16:23:21 +01:00
|
|
|
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 *handler;
|
|
|
|
void *zap_thread;
|
|
|
|
void *server;
|
|
|
|
void *server_mon;
|
|
|
|
char my_endpoint[MAX_SOCKET_STRING];
|
|
|
|
|
|
|
|
void setUp ()
|
|
|
|
{
|
2019-03-20 16:03:06 +01:00
|
|
|
setup_test_context ();
|
|
|
|
setup_context_and_server_side (&handler, &zap_thread, &server, &server_mon,
|
|
|
|
my_endpoint);
|
2018-02-04 16:23:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void tearDown ()
|
|
|
|
{
|
2019-03-20 16:03:06 +01:00
|
|
|
shutdown_context_and_server_side (zap_thread, server, server_mon, handler);
|
|
|
|
teardown_test_context ();
|
2018-02-04 16:23:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
const int timeout = 250;
|
|
|
|
|
2017-09-07 11:21:13 +02:00
|
|
|
const char large_routing_id[] = "0123456789012345678901234567890123456789"
|
2018-02-01 11:46:09 +01:00
|
|
|
"0123456789012345678901234567890123456789"
|
|
|
|
"0123456789012345678901234567890123456789"
|
|
|
|
"0123456789012345678901234567890123456789"
|
|
|
|
"0123456789012345678901234567890123456789"
|
|
|
|
"0123456789012345678901234567890123456789"
|
|
|
|
"012345678901234";
|
2017-08-15 19:42:31 +02:00
|
|
|
|
2019-03-20 16:03:06 +01:00
|
|
|
static void zap_handler_large_routing_id (void * /*unused_*/)
|
2017-08-15 19:42:31 +02:00
|
|
|
{
|
2019-03-20 16:03:06 +01:00
|
|
|
zap_handler_generic (zap_ok, large_routing_id);
|
2017-08-15 19:42:31 +02:00
|
|
|
}
|
|
|
|
|
2019-03-20 16:03:06 +01:00
|
|
|
void expect_new_client_curve_bounce_fail (char *server_public_,
|
2018-05-27 07:01:36 -04:00
|
|
|
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_};
|
2017-09-19 11:05:46 +02:00
|
|
|
expect_new_client_bounce_fail (
|
2019-03-20 16:03:06 +01:00
|
|
|
my_endpoint_, server_, socket_config_curve_client, &curve_client_data,
|
|
|
|
client_mon_, expected_client_event_, expected_client_value_);
|
2017-08-04 15:11:14 +02:00
|
|
|
}
|
|
|
|
|
2019-03-20 16:03:06 +01:00
|
|
|
void test_null_key (void *server_,
|
2018-05-27 07:01:36 -04:00
|
|
|
void *server_mon_,
|
|
|
|
char *my_endpoint_,
|
|
|
|
char *server_public_,
|
|
|
|
char *client_public_,
|
|
|
|
char *client_secret_)
|
2017-08-04 15:11:14 +02:00
|
|
|
{
|
2019-03-20 16:03:06 +01:00
|
|
|
expect_new_client_curve_bounce_fail (server_public_, client_public_,
|
2018-05-27 07:01:36 -04:00
|
|
|
client_secret_, my_endpoint_, server_);
|
2013-09-30 15:14:02 +02:00
|
|
|
|
2017-08-04 16:05:20 +02:00
|
|
|
int handshake_failed_encryption_event_count =
|
2018-05-27 07:01:36 -04:00
|
|
|
expect_monitor_event_multiple (server_mon_,
|
2017-08-17 17:54:07 +02:00
|
|
|
ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
|
|
|
|
ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC);
|
2017-08-03 15:15:56 +02:00
|
|
|
|
2018-02-01 11:46:09 +01:00
|
|
|
// handshake_failed_encryption_event_count should be at least two because
|
2017-08-03 15:15:56 +02:00
|
|
|
// expect_bounce_fail involves two exchanges
|
2018-02-01 11:46:09 +01:00
|
|
|
// 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
|
2017-08-03 15:15:56 +02:00
|
|
|
// long)
|
2017-08-04 16:05:20 +02:00
|
|
|
|
|
|
|
fprintf (stderr,
|
2017-08-18 13:19:07 +02:00
|
|
|
"count of "
|
|
|
|
"ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL/"
|
|
|
|
"ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC events: %i\n",
|
2017-08-04 16:05:20 +02:00
|
|
|
handshake_failed_encryption_event_count);
|
2017-08-03 15:15:56 +02:00
|
|
|
}
|
|
|
|
|
2018-02-04 16:23:21 +01:00
|
|
|
void test_curve_security_with_valid_credentials ()
|
2017-08-03 15:15:56 +02:00
|
|
|
{
|
2017-08-17 10:30:34 +02:00
|
|
|
curve_client_data_t curve_client_data = {
|
|
|
|
valid_server_public, valid_client_public, valid_client_secret};
|
2017-08-18 13:19:07 +02:00
|
|
|
void *client_mon;
|
2019-03-20 16:03:06 +01:00
|
|
|
void *client = create_and_connect_client (
|
|
|
|
my_endpoint, socket_config_curve_client, &curve_client_data, &client_mon);
|
2017-08-03 15:15:56 +02:00
|
|
|
bounce (server, client);
|
2019-03-20 16:03:06 +01:00
|
|
|
test_context_socket_close (client);
|
2013-09-09 20:40:34 +02:00
|
|
|
|
2017-08-07 18:07:37 +02:00
|
|
|
int event = get_monitor_event_with_timeout (server_mon, NULL, NULL, -1);
|
2017-08-03 15:15:56 +02:00
|
|
|
assert (event == ZMQ_EVENT_HANDSHAKE_SUCCEEDED);
|
|
|
|
|
|
|
|
assert_no_more_monitor_events_with_timeout (server_mon, timeout);
|
2017-08-18 13:19:07 +02:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2019-03-20 16:03:06 +01:00
|
|
|
test_context_socket_close (client_mon);
|
2017-08-03 15:15:56 +02:00
|
|
|
}
|
2016-12-31 00:08:05 +01:00
|
|
|
|
2018-02-04 16:23:21 +01:00
|
|
|
void test_curve_security_with_bogus_client_credentials ()
|
2017-08-03 15:15:56 +02:00
|
|
|
{
|
2013-09-02 17:22:24 +02:00
|
|
|
// This must be caught by the ZAP handler
|
2018-02-01 11:46:09 +01:00
|
|
|
char bogus_public[41];
|
|
|
|
char bogus_secret[41];
|
2013-09-30 15:14:02 +02:00
|
|
|
zmq_curve_keypair (bogus_public, bogus_secret);
|
2013-09-09 20:40:34 +02:00
|
|
|
|
2018-11-18 11:37:52 +00:00
|
|
|
expect_new_client_curve_bounce_fail (
|
2019-03-20 16:03:06 +01:00
|
|
|
valid_server_public, bogus_public, bogus_secret, my_endpoint, server,
|
2018-11-18 11:37:52 +00:00
|
|
|
NULL, ZMQ_EVENT_HANDSHAKE_FAILED_AUTH, 400);
|
2013-09-09 20:40:34 +02:00
|
|
|
|
2018-02-01 11:46:09 +01:00
|
|
|
int server_event_count = 0;
|
2017-08-18 13:19:07 +02:00
|
|
|
server_event_count = expect_monitor_event_multiple (
|
2017-08-17 17:54:07 +02:00
|
|
|
server_mon, ZMQ_EVENT_HANDSHAKE_FAILED_AUTH, 400);
|
2018-02-04 16:23:21 +01:00
|
|
|
TEST_ASSERT_LESS_OR_EQUAL_INT (1, server_event_count);
|
2017-08-04 15:11:14 +02:00
|
|
|
|
|
|
|
// there may be more than one ZAP request due to repeated attempts by the client
|
2018-02-04 16:23:21 +01:00
|
|
|
TEST_ASSERT (0 == server_event_count
|
|
|
|
|| 1 <= zmq_atomic_counter_value (zap_requests_handled));
|
2017-08-03 15:15:56 +02:00
|
|
|
}
|
2016-12-31 00:08:05 +01:00
|
|
|
|
2018-05-27 07:01:36 -04:00
|
|
|
void expect_zmtp_mechanism_mismatch (void *client_,
|
|
|
|
char *my_endpoint_,
|
|
|
|
void *server_,
|
|
|
|
void *server_mon_)
|
2017-08-03 15:15:56 +02:00
|
|
|
{
|
2014-09-19 19:24:45 +02:00
|
|
|
// This must be caught by the curve_server class, not passed to ZAP
|
2018-05-27 07:01:36 -04:00
|
|
|
int rc = zmq_connect (client_, my_endpoint_);
|
2018-02-04 16:23:21 +01:00
|
|
|
TEST_ASSERT_ZMQ_ERRNO (rc == 0);
|
2018-05-27 07:01:36 -04:00
|
|
|
expect_bounce_fail (server_, client_);
|
2019-03-20 16:03:06 +01:00
|
|
|
test_context_socket_close_zero_linger (client_);
|
2014-09-18 07:32:07 +02:00
|
|
|
|
2018-05-27 07:01:36 -04:00
|
|
|
expect_monitor_event_multiple (server_mon_,
|
2017-08-17 17:54:07 +02:00
|
|
|
ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
|
|
|
|
ZMQ_PROTOCOL_ERROR_ZMTP_MECHANISM_MISMATCH);
|
2017-08-04 15:11:14 +02:00
|
|
|
|
2018-02-04 16:23:21 +01:00
|
|
|
TEST_ASSERT_EQUAL_INT (0, zmq_atomic_counter_value (zap_requests_handled));
|
2017-08-03 15:15:56 +02:00
|
|
|
}
|
2016-12-31 00:08:05 +01:00
|
|
|
|
2018-02-04 16:23:21 +01:00
|
|
|
void test_curve_security_with_null_client_credentials ()
|
2017-08-04 15:11:14 +02:00
|
|
|
{
|
2019-03-20 16:03:06 +01:00
|
|
|
void *client = test_context_socket (ZMQ_DEALER);
|
2017-08-04 15:11:14 +02:00
|
|
|
|
2017-08-17 17:54:07 +02:00
|
|
|
expect_zmtp_mechanism_mismatch (client, my_endpoint, server, server_mon);
|
2017-08-04 15:11:14 +02:00
|
|
|
}
|
|
|
|
|
2018-02-04 16:23:21 +01:00
|
|
|
void test_curve_security_with_plain_client_credentials ()
|
2017-08-03 15:15:56 +02:00
|
|
|
{
|
2019-03-20 16:03:06 +01:00
|
|
|
void *client = test_context_socket (ZMQ_DEALER);
|
2017-08-03 15:15:56 +02:00
|
|
|
int rc = zmq_setsockopt (client, ZMQ_PLAIN_USERNAME, "admin", 5);
|
2018-02-04 16:23:21 +01:00
|
|
|
TEST_ASSERT_ZMQ_ERRNO (rc == 0);
|
2014-09-18 07:32:07 +02:00
|
|
|
rc = zmq_setsockopt (client, ZMQ_PLAIN_PASSWORD, "password", 8);
|
2018-02-04 16:23:21 +01:00
|
|
|
TEST_ASSERT_ZMQ_ERRNO (rc == 0);
|
2017-08-04 11:35:00 +02:00
|
|
|
|
2017-08-17 17:54:07 +02:00
|
|
|
expect_zmtp_mechanism_mismatch (client, my_endpoint, server, server_mon);
|
2017-08-03 15:15:56 +02:00
|
|
|
}
|
2014-11-07 17:35:41 +01:00
|
|
|
|
2018-05-27 07:01:36 -04:00
|
|
|
fd_t connect_vanilla_socket (char *my_endpoint_)
|
2017-08-03 15:15:56 +02:00
|
|
|
{
|
2018-05-14 20:49:58 +02:00
|
|
|
fd_t s;
|
2017-08-15 16:28:24 +02:00
|
|
|
struct sockaddr_in ip4addr;
|
2014-12-03 10:34:34 -08:00
|
|
|
|
2017-05-01 12:11:11 +01:00
|
|
|
unsigned short int port;
|
2018-05-27 07:01:36 -04:00
|
|
|
int rc = sscanf (my_endpoint_, "tcp://127.0.0.1:%hu", &port);
|
2018-02-04 16:23:21 +01:00
|
|
|
TEST_ASSERT_EQUAL_INT (1, rc);
|
2017-05-01 12:11:11 +01:00
|
|
|
|
2014-12-03 10:34:34 -08:00
|
|
|
ip4addr.sin_family = AF_INET;
|
2017-05-01 12:11:11 +01:00
|
|
|
ip4addr.sin_port = htons (port);
|
2017-08-03 15:15:56 +02:00
|
|
|
#if defined(ZMQ_HAVE_WINDOWS) && (_WIN32_WINNT < 0x0600)
|
2015-05-07 16:52:37 -04:00
|
|
|
ip4addr.sin_addr.s_addr = inet_addr ("127.0.0.1");
|
|
|
|
#else
|
2017-08-03 15:15:56 +02:00
|
|
|
inet_pton (AF_INET, "127.0.0.1", &ip4addr.sin_addr);
|
2015-05-07 16:52:37 -04:00
|
|
|
#endif
|
2014-12-03 10:34:34 -08:00
|
|
|
|
|
|
|
s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
2017-08-03 15:15:56 +02:00
|
|
|
rc = connect (s, (struct sockaddr *) &ip4addr, sizeof (ip4addr));
|
2018-02-04 16:23:21 +01:00
|
|
|
TEST_ASSERT_GREATER_THAN_INT (-1, rc);
|
2017-08-15 16:28:24 +02:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2018-02-04 16:23:21 +01:00
|
|
|
void test_curve_security_unauthenticated_message ()
|
2017-08-15 16:28:24 +02:00
|
|
|
{
|
|
|
|
// Unauthenticated messages from a vanilla socket shouldn't be received
|
2018-05-14 20:49:58 +02:00
|
|
|
fd_t s = connect_vanilla_socket (my_endpoint);
|
2014-12-03 14:51:57 -08:00
|
|
|
// 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);
|
2017-08-03 15:15:56 +02:00
|
|
|
|
2014-12-03 10:34:34 -08:00
|
|
|
zmq_setsockopt (server, ZMQ_RCVTIMEO, &timeout, sizeof (timeout));
|
|
|
|
char *buf = s_recv (server);
|
2018-02-04 16:23:21 +01:00
|
|
|
TEST_ASSERT_NULL_MESSAGE (buf, "Received unauthenticated message");
|
2014-12-03 10:34:34 -08:00
|
|
|
close (s);
|
2017-08-03 15:15:56 +02:00
|
|
|
}
|
2014-12-03 10:34:34 -08:00
|
|
|
|
2018-05-27 07:01:36 -04:00
|
|
|
void send_all (fd_t fd_, const char *data_, socket_size_t size_)
|
2017-08-15 16:28:24 +02:00
|
|
|
{
|
2018-05-27 07:01:36 -04:00
|
|
|
while (size_ > 0) {
|
|
|
|
int res = send (fd_, data_, size_, 0);
|
2018-02-04 16:23:21 +01:00
|
|
|
TEST_ASSERT_GREATER_THAN_INT (0, res);
|
2018-05-27 07:01:36 -04:00
|
|
|
size_ -= res;
|
|
|
|
data_ += res;
|
2017-08-15 16:28:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-27 07:01:36 -04:00
|
|
|
template <size_t N> void send (fd_t fd_, const char (&data_)[N])
|
2017-08-15 16:28:24 +02:00
|
|
|
{
|
2018-05-27 07:01:36 -04:00
|
|
|
send_all (fd_, data_, N - 1);
|
2017-08-15 16:28:24 +02:00
|
|
|
}
|
|
|
|
|
2018-05-27 07:01:36 -04:00
|
|
|
void send_greeting (fd_t s_)
|
2017-08-15 16:28:24 +02:00
|
|
|
{
|
2018-05-27 07:01:36 -04:00
|
|
|
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");
|
2017-08-15 16:28:24 +02:00
|
|
|
}
|
|
|
|
|
2018-02-04 16:23:21 +01:00
|
|
|
void test_curve_security_invalid_hello_wrong_length ()
|
2017-08-15 16:28:24 +02:00
|
|
|
{
|
2018-05-14 20:49:58 +02:00
|
|
|
fd_t s = connect_vanilla_socket (my_endpoint);
|
2017-08-15 16:28:24 +02:00
|
|
|
|
|
|
|
// send GREETING
|
|
|
|
send_greeting (s);
|
|
|
|
|
|
|
|
// send CURVE HELLO of wrong size
|
2018-02-01 11:46:09 +01:00
|
|
|
send (s, "\x04\x06\x05HELLO");
|
2017-08-15 16:28:24 +02:00
|
|
|
|
2017-08-17 17:54:07 +02:00
|
|
|
expect_monitor_event_multiple (
|
|
|
|
server_mon, ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
|
|
|
|
ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_HELLO);
|
2017-08-15 16:28:24 +02:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2019-02-11 07:24:56 -05:00
|
|
|
// same as htonll, which is only available on few platforms (recent Windows, but not on Linux, e.g.(
|
|
|
|
static uint64_t host_to_network (uint64_t value_)
|
2017-08-15 16:28:24 +02:00
|
|
|
{
|
|
|
|
// The answer is 42
|
|
|
|
static const int num = 42;
|
|
|
|
|
|
|
|
// Check the endianness
|
|
|
|
if (*reinterpret_cast<const char *> (&num) == num) {
|
2018-05-27 07:01:36 -04:00
|
|
|
const uint32_t high_part = htonl (static_cast<uint32_t> (value_ >> 32));
|
2017-08-15 16:28:24 +02:00
|
|
|
const uint32_t low_part =
|
2018-05-27 07:01:36 -04:00
|
|
|
htonl (static_cast<uint32_t> (value_ & 0xFFFFFFFFLL));
|
2017-08-15 16:28:24 +02:00
|
|
|
|
|
|
|
return (static_cast<uint64_t> (low_part) << 32) | high_part;
|
|
|
|
} else {
|
2018-05-27 07:01:36 -04:00
|
|
|
return value_;
|
2017-08-15 16:28:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-27 07:01:36 -04:00
|
|
|
template <size_t N> void send_command (fd_t s_, char (&command_)[N])
|
2017-08-15 16:28:24 +02:00
|
|
|
{
|
2018-02-01 11:46:09 +01:00
|
|
|
if (N < 256) {
|
2018-05-27 07:01:36 -04:00
|
|
|
send (s_, "\x04");
|
2018-02-01 11:46:09 +01:00
|
|
|
char len = (char) N;
|
2018-05-27 07:01:36 -04:00
|
|
|
send_all (s_, &len, 1);
|
2018-02-01 11:46:09 +01:00
|
|
|
} else {
|
2018-05-27 07:01:36 -04:00
|
|
|
send (s_, "\x06");
|
2019-02-11 07:24:56 -05:00
|
|
|
uint64_t len = host_to_network (N);
|
2018-05-27 07:01:36 -04:00
|
|
|
send_all (s_, (char *) &len, 8);
|
2018-02-01 11:46:09 +01:00
|
|
|
}
|
2018-05-27 07:01:36 -04:00
|
|
|
send_all (s_, command_, N);
|
2017-08-15 16:28:24 +02:00
|
|
|
}
|
|
|
|
|
2018-02-04 16:23:21 +01:00
|
|
|
void test_curve_security_invalid_hello_command_name ()
|
2017-08-15 16:28:24 +02:00
|
|
|
{
|
2018-05-14 20:49:58 +02:00
|
|
|
fd_t s = connect_vanilla_socket (my_endpoint);
|
2017-08-15 16:28:24 +02:00
|
|
|
|
|
|
|
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);
|
2018-02-04 16:23:21 +01:00
|
|
|
TEST_ASSERT_ZMQ_ERRNO (rc == 0);
|
2017-08-15 16:28:24 +02:00
|
|
|
hello[5] = 'X';
|
|
|
|
|
2018-02-01 11:46:09 +01:00
|
|
|
send_command (s, hello);
|
2017-08-15 16:28:24 +02:00
|
|
|
|
2017-08-17 17:54:07 +02:00
|
|
|
expect_monitor_event_multiple (server_mon,
|
|
|
|
ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
|
|
|
|
ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND);
|
2017-08-15 16:28:24 +02:00
|
|
|
|
|
|
|
close (s);
|
|
|
|
}
|
|
|
|
|
2018-02-04 16:23:21 +01:00
|
|
|
void test_curve_security_invalid_hello_version ()
|
2017-08-15 16:28:24 +02:00
|
|
|
{
|
2018-05-14 20:49:58 +02:00
|
|
|
fd_t s = connect_vanilla_socket (my_endpoint);
|
2017-08-15 16:28:24 +02:00
|
|
|
|
|
|
|
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);
|
2018-02-04 16:23:21 +01:00
|
|
|
TEST_ASSERT_ZMQ_ERRNO (rc == 0);
|
2017-08-15 16:28:24 +02:00
|
|
|
hello[6] = 2;
|
|
|
|
|
|
|
|
send_command (s, hello);
|
|
|
|
|
2017-08-17 17:54:07 +02:00
|
|
|
expect_monitor_event_multiple (
|
|
|
|
server_mon, ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
|
|
|
|
ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_HELLO);
|
2017-08-15 16:28:24 +02:00
|
|
|
|
|
|
|
close (s);
|
|
|
|
}
|
|
|
|
|
2018-05-27 07:01:36 -04:00
|
|
|
void flush_read (fd_t fd_)
|
2017-08-15 16:28:24 +02:00
|
|
|
{
|
|
|
|
int res;
|
|
|
|
char buf[256];
|
|
|
|
|
2018-05-27 07:01:36 -04:00
|
|
|
while ((res = recv (fd_, buf, 256, 0)) == 256) {
|
2017-08-15 16:28:24 +02:00
|
|
|
}
|
2018-02-04 16:23:21 +01:00
|
|
|
TEST_ASSERT_NOT_EQUAL (-1, res);
|
2017-08-15 16:28:24 +02:00
|
|
|
}
|
|
|
|
|
2018-05-27 07:01:36 -04:00
|
|
|
void recv_all (fd_t fd_, uint8_t *data_, socket_size_t len_)
|
2017-08-15 16:28:24 +02:00
|
|
|
{
|
2018-05-14 20:49:58 +02:00
|
|
|
socket_size_t received = 0;
|
2018-05-27 07:01:36 -04:00
|
|
|
while (received < len_) {
|
|
|
|
int res = recv (fd_, (char *) data_, len_, 0);
|
2018-02-04 16:23:21 +01:00
|
|
|
TEST_ASSERT_GREATER_THAN_INT (0, res);
|
2018-02-01 11:46:09 +01:00
|
|
|
|
2018-05-27 07:01:36 -04:00
|
|
|
data_ += res;
|
2018-02-01 11:46:09 +01:00
|
|
|
received += res;
|
|
|
|
}
|
2017-08-15 16:28:24 +02:00
|
|
|
}
|
|
|
|
|
2018-05-27 07:01:36 -04:00
|
|
|
void recv_greeting (fd_t fd_)
|
2017-08-15 16:28:24 +02:00
|
|
|
{
|
|
|
|
uint8_t greeting[64];
|
2018-05-27 07:01:36 -04:00
|
|
|
recv_all (fd_, greeting, 64);
|
2017-08-15 16:28:24 +02:00
|
|
|
// TODO assert anything about the greeting received from the server?
|
|
|
|
}
|
|
|
|
|
2018-05-27 07:01:36 -04:00
|
|
|
fd_t connect_exchange_greeting_and_send_hello (
|
|
|
|
char *my_endpoint_, zmq::curve_client_tools_t &tools_)
|
2017-08-15 16:28:24 +02:00
|
|
|
{
|
2018-05-27 07:01:36 -04:00
|
|
|
fd_t s = connect_vanilla_socket (my_endpoint_);
|
2017-08-15 16:28:24 +02:00
|
|
|
|
|
|
|
send_greeting (s);
|
|
|
|
recv_greeting (s);
|
|
|
|
|
|
|
|
// send valid CURVE HELLO
|
|
|
|
char hello[hello_length];
|
2018-05-27 07:01:36 -04:00
|
|
|
int rc = tools_.produce_hello (hello, 0);
|
2018-02-04 16:23:21 +01:00
|
|
|
TEST_ASSERT_ZMQ_ERRNO (rc == 0);
|
2017-08-15 16:28:24 +02:00
|
|
|
|
|
|
|
send_command (s, hello);
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2018-02-04 16:23:21 +01:00
|
|
|
void test_curve_security_invalid_initiate_wrong_length ()
|
2017-08-15 16:28:24 +02:00
|
|
|
{
|
|
|
|
zmq::curve_client_tools_t tools = make_curve_client_tools ();
|
|
|
|
|
2018-05-14 20:49:58 +02:00
|
|
|
fd_t s = connect_exchange_greeting_and_send_hello (my_endpoint, tools);
|
2017-08-15 16:28:24 +02:00
|
|
|
|
|
|
|
// receive but ignore WELCOME
|
|
|
|
flush_read (s);
|
|
|
|
|
|
|
|
int res = get_monitor_event_with_timeout (server_mon, NULL, NULL, timeout);
|
2018-02-04 16:23:21 +01:00
|
|
|
TEST_ASSERT_EQUAL_INT (-1, res);
|
2017-08-15 16:28:24 +02:00
|
|
|
|
2018-02-01 11:46:09 +01:00
|
|
|
send (s, "\x04\x09\x08INITIATE");
|
2017-08-15 16:28:24 +02:00
|
|
|
|
2017-08-17 17:54:07 +02:00
|
|
|
expect_monitor_event_multiple (
|
|
|
|
server_mon, ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
|
|
|
|
ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_INITIATE);
|
2017-08-15 16:28:24 +02:00
|
|
|
|
|
|
|
close (s);
|
|
|
|
}
|
|
|
|
|
2018-05-14 20:49:58 +02:00
|
|
|
fd_t connect_exchange_greeting_and_hello_welcome (
|
2018-05-27 07:01:36 -04:00
|
|
|
char *my_endpoint_,
|
|
|
|
void *server_mon_,
|
|
|
|
int timeout_,
|
|
|
|
zmq::curve_client_tools_t &tools_)
|
2017-08-15 16:28:24 +02:00
|
|
|
{
|
2018-05-27 07:01:36 -04:00
|
|
|
fd_t s = connect_exchange_greeting_and_send_hello (my_endpoint_, tools_);
|
2017-08-15 16:28:24 +02:00
|
|
|
|
|
|
|
// receive but ignore WELCOME
|
|
|
|
uint8_t welcome[welcome_length + 2];
|
|
|
|
recv_all (s, welcome, welcome_length + 2);
|
2018-02-01 11:46:09 +01:00
|
|
|
|
|
|
|
uint8_t cn_precom[crypto_box_BEFORENMBYTES];
|
2018-05-27 07:01:36 -04:00
|
|
|
int res = tools_.process_welcome (welcome + 2, welcome_length, cn_precom);
|
2018-02-04 16:23:21 +01:00
|
|
|
TEST_ASSERT_ZMQ_ERRNO (res == 0);
|
2017-08-15 16:28:24 +02:00
|
|
|
|
2018-05-27 07:01:36 -04:00
|
|
|
res = get_monitor_event_with_timeout (server_mon_, NULL, NULL, timeout_);
|
2018-02-04 16:23:21 +01:00
|
|
|
TEST_ASSERT_EQUAL_INT (-1, res);
|
2017-08-15 16:28:24 +02:00
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2018-02-04 16:23:21 +01:00
|
|
|
void test_curve_security_invalid_initiate_command_name ()
|
2017-08-15 16:28:24 +02:00
|
|
|
{
|
|
|
|
zmq::curve_client_tools_t tools = make_curve_client_tools ();
|
2018-05-14 20:49:58 +02:00
|
|
|
fd_t s = connect_exchange_greeting_and_hello_welcome (
|
2017-08-15 16:28:24 +02:00
|
|
|
my_endpoint, server_mon, timeout, tools);
|
|
|
|
|
2018-02-01 11:46:09 +01:00
|
|
|
char initiate[257];
|
2017-08-15 16:28:24 +02:00
|
|
|
tools.produce_initiate (initiate, 257, 1, NULL, 0);
|
|
|
|
// modify command name
|
|
|
|
initiate[5] = 'X';
|
|
|
|
|
|
|
|
send_command (s, initiate);
|
|
|
|
|
2017-08-17 17:54:07 +02:00
|
|
|
expect_monitor_event_multiple (server_mon,
|
|
|
|
ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
|
|
|
|
ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND);
|
2017-08-15 16:28:24 +02:00
|
|
|
|
|
|
|
close (s);
|
|
|
|
}
|
|
|
|
|
2018-02-04 16:23:21 +01:00
|
|
|
void test_curve_security_invalid_initiate_command_encrypted_cookie ()
|
2017-08-15 16:28:24 +02:00
|
|
|
{
|
|
|
|
zmq::curve_client_tools_t tools = make_curve_client_tools ();
|
2018-05-14 20:49:58 +02:00
|
|
|
fd_t s = connect_exchange_greeting_and_hello_welcome (
|
2017-08-15 16:28:24 +02:00
|
|
|
my_endpoint, server_mon, timeout, tools);
|
|
|
|
|
2018-02-01 11:46:09 +01:00
|
|
|
char initiate[257];
|
2017-08-15 16:28:24 +02:00
|
|
|
tools.produce_initiate (initiate, 257, 1, NULL, 0);
|
|
|
|
// make garbage from encrypted cookie
|
|
|
|
initiate[30] = !initiate[30];
|
|
|
|
|
|
|
|
send_command (s, initiate);
|
|
|
|
|
2017-08-17 17:54:07 +02:00
|
|
|
expect_monitor_event_multiple (server_mon,
|
|
|
|
ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
|
|
|
|
ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC);
|
2017-08-15 16:28:24 +02:00
|
|
|
|
|
|
|
close (s);
|
|
|
|
}
|
|
|
|
|
2018-02-04 16:23:21 +01:00
|
|
|
void test_curve_security_invalid_initiate_command_encrypted_content ()
|
2017-08-15 16:28:24 +02:00
|
|
|
{
|
|
|
|
zmq::curve_client_tools_t tools = make_curve_client_tools ();
|
2018-05-14 20:49:58 +02:00
|
|
|
fd_t s = connect_exchange_greeting_and_hello_welcome (
|
2017-08-15 16:28:24 +02:00
|
|
|
my_endpoint, server_mon, timeout, tools);
|
|
|
|
|
2018-02-01 11:46:09 +01:00
|
|
|
char initiate[257];
|
2017-08-15 16:28:24 +02:00
|
|
|
tools.produce_initiate (initiate, 257, 1, NULL, 0);
|
|
|
|
// make garbage from encrypted content
|
|
|
|
initiate[150] = !initiate[150];
|
|
|
|
|
|
|
|
send_command (s, initiate);
|
|
|
|
|
2017-08-17 17:54:07 +02:00
|
|
|
expect_monitor_event_multiple (server_mon,
|
|
|
|
ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
|
|
|
|
ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC);
|
2017-08-15 16:28:24 +02:00
|
|
|
|
|
|
|
close (s);
|
|
|
|
}
|
|
|
|
|
2018-05-27 07:01:36 -04:00
|
|
|
void test_curve_security_invalid_keysize (void *ctx_)
|
2017-08-03 15:15:56 +02:00
|
|
|
{
|
2014-11-07 17:35:41 +01:00
|
|
|
// Check return codes for invalid buffer sizes
|
2018-05-27 07:01:36 -04:00
|
|
|
void *client = zmq_socket (ctx_, ZMQ_DEALER);
|
2018-02-04 16:23:21 +01:00
|
|
|
TEST_ASSERT_NOT_NULL (client);
|
2014-11-07 17:35:41 +01:00
|
|
|
errno = 0;
|
2018-02-01 11:46:09 +01:00
|
|
|
int rc =
|
|
|
|
zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, valid_server_public, 123);
|
2014-11-07 17:35:41 +01:00
|
|
|
assert (rc == -1 && errno == EINVAL);
|
|
|
|
errno = 0;
|
2017-08-04 15:11:14 +02:00
|
|
|
rc = zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, valid_client_public, 123);
|
2014-11-07 17:35:41 +01:00
|
|
|
assert (rc == -1 && errno == EINVAL);
|
|
|
|
errno = 0;
|
2017-08-04 15:11:14 +02:00
|
|
|
rc = zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, valid_client_secret, 123);
|
2014-11-07 17:35:41 +01:00
|
|
|
assert (rc == -1 && errno == EINVAL);
|
|
|
|
rc = zmq_close (client);
|
2018-02-04 16:23:21 +01:00
|
|
|
TEST_ASSERT_ZMQ_ERRNO (rc == 0);
|
2017-08-03 15:15:56 +02:00
|
|
|
}
|
2014-11-07 17:35:41 +01:00
|
|
|
|
2018-02-04 16:23:21 +01:00
|
|
|
// TODO why isn't this const?
|
|
|
|
char null_key[] = "0000000000000000000000000000000000000000";
|
2017-08-03 15:15:56 +02:00
|
|
|
|
2018-02-04 16:23:21 +01:00
|
|
|
void test_null_server_key ()
|
|
|
|
{
|
2017-08-18 13:19:07 +02:00
|
|
|
// Check CURVE security with a null server key
|
2017-08-03 15:15:56 +02:00
|
|
|
// This will be caught by the curve_server class, not passed to ZAP
|
2019-03-20 16:03:06 +01:00
|
|
|
test_null_key (server, server_mon, my_endpoint, null_key,
|
2017-09-07 09:29:46 +02:00
|
|
|
valid_client_public, valid_client_secret);
|
2018-02-04 16:23:21 +01:00
|
|
|
}
|
2017-08-03 15:15:56 +02:00
|
|
|
|
2018-02-04 16:23:21 +01:00
|
|
|
void test_null_client_public_key ()
|
|
|
|
{
|
2017-08-18 13:19:07 +02:00
|
|
|
// Check CURVE security with a null client public key
|
2017-08-03 15:15:56 +02:00
|
|
|
// This will be caught by the curve_server class, not passed to ZAP
|
2019-03-20 16:03:06 +01:00
|
|
|
test_null_key (server, server_mon, my_endpoint, valid_server_public,
|
2017-09-07 09:29:46 +02:00
|
|
|
null_key, valid_client_secret);
|
2018-02-04 16:23:21 +01:00
|
|
|
}
|
2017-08-03 15:15:56 +02:00
|
|
|
|
2018-02-04 16:23:21 +01:00
|
|
|
void test_null_client_secret_key ()
|
|
|
|
{
|
|
|
|
// Check CURVE security with a null client public key
|
2017-08-03 15:15:56 +02:00
|
|
|
// This will be caught by the curve_server class, not passed to ZAP
|
2019-03-20 16:03:06 +01:00
|
|
|
test_null_key (server, server_mon, my_endpoint, valid_server_public,
|
2017-09-07 09:29:46 +02:00
|
|
|
valid_client_public, null_key);
|
2018-02-04 16:23:21 +01:00
|
|
|
}
|
2017-08-03 15:15:56 +02:00
|
|
|
|
2017-08-08 14:10:20 +02:00
|
|
|
|
2018-02-04 16:23:21 +01:00
|
|
|
int main (void)
|
|
|
|
{
|
|
|
|
if (!zmq_has ("curve")) {
|
|
|
|
printf ("CURVE encryption not installed, skipping test\n");
|
|
|
|
return 0;
|
|
|
|
}
|
2017-08-15 16:28:24 +02:00
|
|
|
|
2018-02-04 16:23:21 +01:00
|
|
|
zmq::random_open ();
|
2017-08-15 16:28:24 +02:00
|
|
|
|
2018-02-04 16:23:21 +01:00
|
|
|
setup_testutil_security_curve ();
|
2017-08-15 16:28:24 +02:00
|
|
|
|
|
|
|
|
2018-02-04 16:23:21 +01:00
|
|
|
setup_test_environment ();
|
2017-08-15 16:28:24 +02:00
|
|
|
|
2018-02-04 16:23:21 +01:00
|
|
|
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);
|
2017-08-15 16:28:24 +02:00
|
|
|
|
2018-02-04 16:23:21 +01:00
|
|
|
// 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
|
2017-09-07 11:21:13 +02:00
|
|
|
// test with a large routing id (resulting in large metadata)
|
2017-09-07 09:29:46 +02:00
|
|
|
fprintf (stderr,
|
2017-09-07 11:21:13 +02:00
|
|
|
"test_curve_security_with_valid_credentials (large routing id)\n");
|
2019-03-20 16:03:06 +01:00
|
|
|
setup_test_context ();
|
|
|
|
setup_context_and_server_side (&handler, &zap_thread, &server, &server_mon,
|
|
|
|
my_endpoint, &zap_handler_large_routing_id,
|
|
|
|
&socket_config_curve_server,
|
|
|
|
&valid_server_secret, large_routing_id);
|
2018-02-04 16:23:21 +01:00
|
|
|
test_curve_security_with_valid_credentials ();
|
2019-03-20 16:03:06 +01:00
|
|
|
shutdown_context_and_server_side (zap_thread, server, server_mon, handler);
|
|
|
|
teardown_test_context ();
|
2017-08-15 19:42:31 +02:00
|
|
|
|
2019-03-20 16:03:06 +01:00
|
|
|
void *ctx = zmq_ctx_new ();
|
2017-08-03 15:15:56 +02:00
|
|
|
test_curve_security_invalid_keysize (ctx);
|
2017-08-17 11:45:18 +02:00
|
|
|
int rc = zmq_ctx_term (ctx);
|
2018-02-04 16:23:21 +01:00
|
|
|
TEST_ASSERT_ZMQ_ERRNO (rc == 0);
|
2013-06-22 16:17:25 +01:00
|
|
|
|
2017-08-15 16:28:24 +02:00
|
|
|
zmq::random_close ();
|
|
|
|
|
2018-02-04 16:23:21 +01:00
|
|
|
return UNITY_END ();
|
2013-06-22 16:17:25 +01:00
|
|
|
}
|