Commit a5f94cb6 authored by sigiesec's avatar sigiesec

Problem: tests without ZAP handler are failing

Solution: emit events as expected by tests, and refuse connections when
ZAP is required but no handler started

Addresses #2711 partially
parent 13b972b2
...@@ -394,12 +394,18 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_) ...@@ -394,12 +394,18 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_)
// Note that rc will be -1 only if ZAP is not set up (Stonehouse pattern - // Note that rc will be -1 only if ZAP is not set up (Stonehouse pattern -
// encryption without authentication), but if it was requested and it does // encryption without authentication), but if it was requested and it does
// not work properly the program will abort. // not work properly the program will abort.
rc = session->zap_connect (); if (zap_required ()) {
if (rc == 0) { rc = session->zap_connect ();
send_zap_request (client_key); if (rc == 0) {
rc = receive_and_process_zap_reply (); send_zap_request (client_key);
if (rc == -1) rc = receive_and_process_zap_reply ();
if (rc == -1)
return -1;
} else {
session->get_socket ()->event_handshake_failed_no_detail (
session->get_endpoint (), EFAULT);
return -1; return -1;
}
} else } else
state = sending_ready; state = sending_ready;
...@@ -472,4 +478,10 @@ void zmq::curve_server_t::send_zap_request (const uint8_t *key) ...@@ -472,4 +478,10 @@ void zmq::curve_server_t::send_zap_request (const uint8_t *key)
zap_client_t::send_zap_request ("CURVE", 5, key, crypto_box_PUBLICKEYBYTES); zap_client_t::send_zap_request ("CURVE", 5, key, crypto_box_PUBLICKEYBYTES);
} }
bool zmq::curve_server_t::zap_required () const
{
// TODO: make this explicit by a separate option zap_required (uniformly across all mechanisms)
return !options.zap_domain.empty();
}
#endif #endif
...@@ -82,6 +82,7 @@ namespace zmq ...@@ -82,6 +82,7 @@ namespace zmq
int produce_error (msg_t *msg_) const; int produce_error (msg_t *msg_) const;
void send_zap_request (const uint8_t *key); void send_zap_request (const uint8_t *key);
bool zap_required () const;
}; };
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning (pop) #pragma warning (pop)
......
...@@ -48,15 +48,9 @@ zmq::null_mechanism_t::null_mechanism_t (session_base_t *session_, ...@@ -48,15 +48,9 @@ zmq::null_mechanism_t::null_mechanism_t (session_base_t *session_,
error_command_sent (false), error_command_sent (false),
ready_command_received (false), ready_command_received (false),
error_command_received (false), error_command_received (false),
zap_connected (false),
zap_request_sent (false), zap_request_sent (false),
zap_reply_received (false) zap_reply_received (false)
{ {
// NULL mechanism only uses ZAP if there's a domain defined
// This prevents ZAP requests on naive sockets
if (options.zap_domain.size () > 0
&& session->zap_connect () == 0)
zap_connected = true;
} }
zmq::null_mechanism_t::~null_mechanism_t () zmq::null_mechanism_t::~null_mechanism_t ()
...@@ -69,14 +63,23 @@ int zmq::null_mechanism_t::next_handshake_command (msg_t *msg_) ...@@ -69,14 +63,23 @@ int zmq::null_mechanism_t::next_handshake_command (msg_t *msg_)
errno = EAGAIN; errno = EAGAIN;
return -1; return -1;
} }
if (zap_connected && !zap_reply_received) {
if (zap_required() && !zap_reply_received) {
if (zap_request_sent) { if (zap_request_sent) {
errno = EAGAIN; errno = EAGAIN;
return -1; return -1;
} }
int rc = session->zap_connect();
if (rc == -1)
{
session->get_socket()->event_handshake_failed_no_detail (
session->get_endpoint(),
EFAULT);
return -1;
}
send_zap_request (); send_zap_request ();
zap_request_sent = true; zap_request_sent = true;
int rc = receive_and_process_zap_reply (); rc = receive_and_process_zap_reply ();
if (rc == -1 || rc == 1) if (rc == -1 || rc == 1)
return -1; return -1;
zap_reply_received = true; zap_reply_received = true;
...@@ -205,6 +208,13 @@ zmq::mechanism_t::status_t zmq::null_mechanism_t::status () const ...@@ -205,6 +208,13 @@ zmq::mechanism_t::status_t zmq::null_mechanism_t::status () const
return handshaking; return handshaking;
} }
bool zmq::null_mechanism_t::zap_required() const
{
// NULL mechanism only uses ZAP if there's a domain defined
// This prevents ZAP requests on naive sockets
return options.zap_domain.size() > 0;
}
void zmq::null_mechanism_t::send_zap_request () void zmq::null_mechanism_t::send_zap_request ()
{ {
zap_client_t::send_zap_request ("NULL", 4, NULL, NULL, 0); zap_client_t::send_zap_request ("NULL", 4, NULL, NULL, 0);
......
...@@ -55,13 +55,14 @@ namespace zmq ...@@ -55,13 +55,14 @@ namespace zmq
virtual int zap_msg_available (); virtual int zap_msg_available ();
virtual status_t status () const; virtual status_t status () const;
bool zap_required () const;
private: private:
bool ready_command_sent; bool ready_command_sent;
bool error_command_sent; bool error_command_sent;
bool ready_command_received; bool ready_command_received;
bool error_command_received; bool error_command_received;
bool zap_connected;
bool zap_request_sent; bool zap_request_sent;
bool zap_reply_received; bool zap_reply_received;
......
...@@ -178,7 +178,11 @@ int zmq::plain_server_t::process_hello (msg_t *msg_) ...@@ -178,7 +178,11 @@ int zmq::plain_server_t::process_hello (msg_t *msg_)
// failure. // failure.
rc = session->zap_connect (); rc = session->zap_connect ();
if (rc != 0) if (rc != 0)
{
session->get_socket()->event_handshake_failed_no_detail(
session->get_endpoint(), EFAULT);
return -1; return -1;
}
send_zap_request (username, password); send_zap_request (username, password);
return receive_and_process_zap_reply () == -1 ? -1 : 0; return receive_and_process_zap_reply () == -1 ? -1 : 0;
} }
......
...@@ -59,6 +59,29 @@ static void zap_handler_too_many_parts (void *ctx) ...@@ -59,6 +59,29 @@ static void zap_handler_too_many_parts (void *ctx)
zap_handler_generic (ctx, zap_too_many_parts); zap_handler_generic (ctx, zap_too_many_parts);
} }
int expect_new_client_bounce_fail_and_count_monitor_events (
void *ctx,
char *my_endpoint,
void *server,
socket_config_fn socket_config_,
void *socket_config_data_,
void **client_mon,
void *server_mon,
int expected_event,
int expected_err)
{
expect_new_client_bounce_fail (ctx, my_endpoint, server, socket_config_,
socket_config_data_, client_mon);
int events_received = 0;
#ifdef ZMQ_BUILD_DRAFT_API
events_received =
expect_monitor_event_multiple (server_mon, expected_event, expected_err);
#endif
return events_received;
}
void test_zap_unsuccessful (void *ctx, void test_zap_unsuccessful (void *ctx,
char *my_endpoint, char *my_endpoint,
void *server, void *server,
...@@ -69,21 +92,41 @@ void test_zap_unsuccessful (void *ctx, ...@@ -69,21 +92,41 @@ void test_zap_unsuccessful (void *ctx,
void *socket_config_data_, void *socket_config_data_,
void **client_mon = NULL) void **client_mon = NULL)
{ {
expect_new_client_bounce_fail (ctx, my_endpoint, server, socket_config_, int events_received =
socket_config_data_, client_mon); expect_new_client_bounce_fail_and_count_monitor_events (
ctx, my_endpoint, server, socket_config_, socket_config_data_,
int events_received = 0; client_mon, server_mon, expected_event, expected_err);
#ifdef ZMQ_BUILD_DRAFT_API
events_received =
expect_monitor_event_multiple (server_mon, expected_event, expected_err);
#endif
// there may be more than one ZAP request due to repeated attempts by the // there may be more than one ZAP request due to repeated attempts by the
// client (actually only in case if ZAP status code 300) // client (actually only in case if ZAP status code 300)
assert (events_received == 0 assert (events_received == 0
|| 1 <= zmq_atomic_counter_value (zap_requests_handled)); || 1 <= zmq_atomic_counter_value (zap_requests_handled));
} }
void test_zap_unsuccessful_no_handler (void *ctx,
char *my_endpoint,
void *server,
void *server_mon,
int expected_event,
int expected_err,
socket_config_fn socket_config_,
void *socket_config_data_,
void **client_mon = NULL)
{
int events_received =
expect_new_client_bounce_fail_and_count_monitor_events (
ctx, my_endpoint, server, socket_config_, socket_config_data_,
client_mon, server_mon, expected_event, expected_err);
#ifdef ZMQ_BUILD_DRAFT_API
// there may be more than one ZAP request due to repeated attempts by the
// client
assert (events_received > 0);
#else
LIBZMQ_UNUSED (events_received);
#endif
}
void test_zap_protocol_error (void *ctx, void test_zap_protocol_error (void *ctx,
char *my_endpoint, char *my_endpoint,
void *server, void *server,
...@@ -147,7 +190,7 @@ void test_zap_unsuccessful_status_500 (void *ctx, ...@@ -147,7 +190,7 @@ void test_zap_unsuccessful_status_500 (void *ctx,
int events_received = 0; int events_received = 0;
events_received = expect_monitor_event_multiple ( events_received = expect_monitor_event_multiple (
client_mon, ZMQ_EVENT_HANDSHAKE_FAILED_AUTH, 500, true); client_mon, ZMQ_EVENT_HANDSHAKE_FAILED_AUTH, 500, true);
// this should actually be events_received == 1, but this is not always // this should actually be events_received == 1, but this is not always
// true, see https://github.com/zeromq/libzmq/issues/2705 // true, see https://github.com/zeromq/libzmq/issues/2705
assert (events_received <= 1); assert (events_received <= 1);
...@@ -266,18 +309,20 @@ void test_zap_errors (socket_config_fn server_socket_config_, ...@@ -266,18 +309,20 @@ void test_zap_errors (socket_config_fn server_socket_config_,
client_socket_config_data_); client_socket_config_data_);
shutdown_context_and_server_side (ctx, zap_thread, server, server_mon, shutdown_context_and_server_side (ctx, zap_thread, server, server_mon,
handler); handler);
// no ZAP handler // no ZAP handler
fprintf (stderr, "test_zap_unsuccessful no ZAP handler started\n"); fprintf (stderr, "test_zap_unsuccessful no ZAP handler started\n");
setup_context_and_server_side ( setup_context_and_server_side (&ctx, &handler, &zap_thread, &server,
&ctx, &handler, &zap_thread, &server, &server_mon, my_endpoint, &server_mon, my_endpoint, NULL,
NULL, server_socket_config_); server_socket_config_);
test_zap_unsuccessful (ctx, my_endpoint, server, server_mon, test_zap_unsuccessful_no_handler (
ctx, my_endpoint, server, server_mon,
#ifdef ZMQ_BUILD_DRAFT_API #ifdef ZMQ_BUILD_DRAFT_API
ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL, EFAULT, ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL, EFAULT,
#else #else
0, 0, 0, 0,
#endif #endif
client_socket_config_, client_socket_config_data_); client_socket_config_, client_socket_config_data_);
shutdown_context_and_server_side (ctx, zap_thread, server, server_mon, shutdown_context_and_server_side (ctx, zap_thread, server, server_mon,
handler); handler);
} }
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment