mirror of
https://github.com/zeromq/libzmq.git
synced 2025-02-23 15:14:40 +01:00
Problem: ZAP status codes != 200 do not result in an appropriate monitor event (#2665)
* Problem: missing test for status code 300, inadequate assertion for status code 500 Solution: add test, change assertion (currently test fails) * Problem: gcc compiler error deprecated conversion from string constant Solution: declare variable as const * Problem: in case of ZAP handler returning a status code other than 200, no appropriate event is emitted Solution: immediately emit event after receiving reply from ZAP handler * Problem: endpoint address is not included in zap-reply monitor event Solution: added functions to retrieve endpoint address in zmq::i_engine and zmq::session_base_t removed unused code block in zmq::stream_engine_t::next_handshake_command * Problem: wrong formatting Solution: fix formatting * Problem: test fails because of EPIPE Solution: add EPIPE/ECONNRESET/ECONNAGAIN handling for more test cases
This commit is contained in:
parent
834b9e4cd7
commit
a6cef4ef86
@ -248,9 +248,7 @@ int zmq::curve_server_t::zap_msg_available ()
|
|||||||
}
|
}
|
||||||
const int rc = receive_and_process_zap_reply ();
|
const int rc = receive_and_process_zap_reply ();
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
state = status_code == "200"
|
handle_zap_status_code ();
|
||||||
? send_ready
|
|
||||||
: send_error;
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -506,9 +504,7 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_)
|
|||||||
return -1;
|
return -1;
|
||||||
rc = receive_and_process_zap_reply ();
|
rc = receive_and_process_zap_reply ();
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
state = status_code == "200"
|
handle_zap_status_code ();
|
||||||
? send_ready
|
|
||||||
: send_error;
|
|
||||||
else
|
else
|
||||||
if (errno == EAGAIN)
|
if (errno == EAGAIN)
|
||||||
state = expect_zap_reply;
|
state = expect_zap_reply;
|
||||||
@ -708,8 +704,11 @@ int zmq::curve_server_t::receive_and_process_zap_reply ()
|
|||||||
return close_and_return (msg, -1);
|
return close_and_return (msg, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Status code frame
|
// Status code frame, only 200, 300, 400 and 500 are valid status codes
|
||||||
if (msg [3].size () != 3) {
|
char *status_code_data = static_cast <char*> (msg [3].data());
|
||||||
|
if (msg [3].size () != 3 || status_code_data [0] < '2'
|
||||||
|
|| status_code_data [0] > '5' || status_code_data [1] != '0'
|
||||||
|
|| status_code_data [2] != '0') {
|
||||||
// CURVE I: ZAP handler sent invalid status code
|
// CURVE I: ZAP handler sent invalid status code
|
||||||
current_error_detail = zap;
|
current_error_detail = zap;
|
||||||
errno = EPROTO;
|
errno = EPROTO;
|
||||||
@ -738,4 +737,33 @@ int zmq::curve_server_t::receive_and_process_zap_reply ()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void zmq::curve_server_t::handle_zap_status_code ()
|
||||||
|
{
|
||||||
|
// we can assume here that status_code is a valid ZAP status code,
|
||||||
|
// i.e. 200, 300, 400 or 500
|
||||||
|
if (status_code [0] == '2') {
|
||||||
|
state = send_ready;
|
||||||
|
} else {
|
||||||
|
state = send_error;
|
||||||
|
|
||||||
|
int err = 0;
|
||||||
|
switch (status_code [0]) {
|
||||||
|
case '3':
|
||||||
|
err = EAGAIN;
|
||||||
|
break;
|
||||||
|
case '4':
|
||||||
|
err = EACCES;
|
||||||
|
break;
|
||||||
|
case '5':
|
||||||
|
err = EFAULT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// TODO use event_handshake_failed_zap here? but this is not a ZAP
|
||||||
|
// protocol error
|
||||||
|
|
||||||
|
session->get_socket ()->event_handshake_failed_no_detail (
|
||||||
|
session->get_endpoint (), err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -131,6 +131,7 @@ namespace zmq
|
|||||||
|
|
||||||
int send_zap_request (const uint8_t *key);
|
int send_zap_request (const uint8_t *key);
|
||||||
int receive_and_process_zap_reply ();
|
int receive_and_process_zap_reply ();
|
||||||
|
void handle_zap_status_code ();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,9 @@ namespace zmq
|
|||||||
virtual void restart_output () = 0;
|
virtual void restart_output () = 0;
|
||||||
|
|
||||||
virtual void zap_msg_available () = 0;
|
virtual void zap_msg_available () = 0;
|
||||||
|
|
||||||
|
virtual const char * get_endpoint() const = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -113,6 +113,11 @@ zmq::session_base_t::session_base_t (class io_thread_t *io_thread_,
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *zmq::session_base_t::get_endpoint () const
|
||||||
|
{
|
||||||
|
return engine->get_endpoint ();
|
||||||
|
}
|
||||||
|
|
||||||
zmq::session_base_t::~session_base_t ()
|
zmq::session_base_t::~session_base_t ()
|
||||||
{
|
{
|
||||||
zmq_assert (!pipe);
|
zmq_assert (!pipe);
|
||||||
|
@ -97,6 +97,7 @@ namespace zmq
|
|||||||
int write_zap_msg (msg_t *msg_);
|
int write_zap_msg (msg_t *msg_);
|
||||||
|
|
||||||
socket_base_t *get_socket ();
|
socket_base_t *get_socket ();
|
||||||
|
const char *get_endpoint () const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -784,19 +784,6 @@ int zmq::stream_engine_t::next_handshake_command (msg_t *msg_)
|
|||||||
|
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
msg_->set_flags (msg_t::command);
|
msg_->set_flags (msg_t::command);
|
||||||
#ifdef ZMQ_BUILD_DRAFT_API
|
|
||||||
if (mechanism->status () == mechanism_t::error) {
|
|
||||||
int err = errno;
|
|
||||||
if (mechanism->error_detail () == mechanism_t::zmtp)
|
|
||||||
socket->event_handshake_failed_zmtp (endpoint, err);
|
|
||||||
else if (mechanism->error_detail () == mechanism_t::zap)
|
|
||||||
socket->event_handshake_failed_zap (endpoint, err);
|
|
||||||
else if (mechanism->error_detail () == mechanism_t::encryption)
|
|
||||||
socket->event_handshake_failed_encryption (endpoint, err);
|
|
||||||
else
|
|
||||||
socket->event_handshake_failed_no_detail (endpoint, err);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -836,6 +823,11 @@ void zmq::stream_engine_t::zap_msg_available ()
|
|||||||
restart_output ();
|
restart_output ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *zmq::stream_engine_t::get_endpoint () const
|
||||||
|
{
|
||||||
|
return endpoint.c_str ();
|
||||||
|
}
|
||||||
|
|
||||||
void zmq::stream_engine_t::mechanism_ready ()
|
void zmq::stream_engine_t::mechanism_ready ()
|
||||||
{
|
{
|
||||||
if (options.heartbeat_interval > 0) {
|
if (options.heartbeat_interval > 0) {
|
||||||
|
@ -79,6 +79,7 @@ namespace zmq
|
|||||||
void restart_input ();
|
void restart_input ();
|
||||||
void restart_output ();
|
void restart_output ();
|
||||||
void zap_msg_available ();
|
void zap_msg_available ();
|
||||||
|
const char *get_endpoint () const;
|
||||||
|
|
||||||
// i_poll_events interface implementation.
|
// i_poll_events interface implementation.
|
||||||
void in_event ();
|
void in_event ();
|
||||||
|
@ -289,6 +289,11 @@ void zmq::udp_engine_t::out_event()
|
|||||||
reset_pollout (handle);
|
reset_pollout (handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *zmq::udp_engine_t::get_endpoint () const
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
void zmq::udp_engine_t::restart_output()
|
void zmq::udp_engine_t::restart_output()
|
||||||
{
|
{
|
||||||
// If we don't support send we just drop all messages
|
// If we don't support send we just drop all messages
|
||||||
|
@ -44,8 +44,9 @@ namespace zmq
|
|||||||
void in_event ();
|
void in_event ();
|
||||||
void out_event ();
|
void out_event ();
|
||||||
|
|
||||||
private:
|
const char *get_endpoint () const;
|
||||||
|
|
||||||
|
private:
|
||||||
int resolve_raw_address (char *addr_, size_t length_);
|
int resolve_raw_address (char *addr_, size_t length_);
|
||||||
void sockaddr_to_msg (zmq::msg_t *msg, sockaddr_in* addr);
|
void sockaddr_to_msg (zmq::msg_t *msg, sockaddr_in* addr);
|
||||||
|
|
||||||
|
@ -141,6 +141,7 @@ enum zap_protocol_t
|
|||||||
{
|
{
|
||||||
zap_ok,
|
zap_ok,
|
||||||
// ZAP-compliant non-standard cases
|
// ZAP-compliant non-standard cases
|
||||||
|
zap_status_temporary_failure,
|
||||||
zap_status_internal_error,
|
zap_status_internal_error,
|
||||||
// ZAP protocol errors
|
// ZAP protocol errors
|
||||||
zap_wrong_version,
|
zap_wrong_version,
|
||||||
@ -210,11 +211,21 @@ static void zap_handler_generic (void *ctx, zap_protocol_t zap_protocol)
|
|||||||
: sequence);
|
: sequence);
|
||||||
|
|
||||||
if (streq (client_key_text, valid_client_public)) {
|
if (streq (client_key_text, valid_client_public)) {
|
||||||
s_sendmore (handler, zap_protocol == zap_status_internal_error
|
const char *status_code;
|
||||||
? "500"
|
switch (zap_protocol) {
|
||||||
: (zap_protocol == zap_status_invalid
|
case zap_status_internal_error:
|
||||||
? "invalid_status"
|
status_code = "500";
|
||||||
: "200"));
|
break;
|
||||||
|
case zap_status_temporary_failure:
|
||||||
|
status_code = "300";
|
||||||
|
break;
|
||||||
|
case zap_status_invalid:
|
||||||
|
status_code = "invalid_status";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
status_code = "200";
|
||||||
|
}
|
||||||
|
s_sendmore (handler, status_code);
|
||||||
s_sendmore (handler, "OK");
|
s_sendmore (handler, "OK");
|
||||||
s_sendmore (handler, "anonymous");
|
s_sendmore (handler, "anonymous");
|
||||||
if (zap_protocol == zap_too_many_parts) {
|
if (zap_protocol == zap_too_many_parts) {
|
||||||
@ -265,6 +276,11 @@ static void zap_handler_wrong_status_invalid (void *ctx)
|
|||||||
zap_handler_generic (ctx, zap_status_invalid);
|
zap_handler_generic (ctx, zap_status_invalid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void zap_handler_wrong_status_temporary_failure (void *ctx)
|
||||||
|
{
|
||||||
|
zap_handler_generic (ctx, zap_status_temporary_failure);
|
||||||
|
}
|
||||||
|
|
||||||
static void zap_handler_wrong_status_internal_error (void *ctx)
|
static void zap_handler_wrong_status_internal_error (void *ctx)
|
||||||
{
|
{
|
||||||
zap_handler_generic (ctx, zap_status_internal_error);
|
zap_handler_generic (ctx, zap_status_internal_error);
|
||||||
@ -322,6 +338,7 @@ int expect_monitor_event_multiple (void *server_mon,
|
|||||||
{
|
{
|
||||||
int count_of_expected_events = 0;
|
int count_of_expected_events = 0;
|
||||||
int client_closed_connection = 0;
|
int client_closed_connection = 0;
|
||||||
|
// infinite timeout at the start
|
||||||
int timeout = -1;
|
int timeout = -1;
|
||||||
|
|
||||||
int event;
|
int event;
|
||||||
@ -512,18 +529,17 @@ void test_curve_security_with_bogus_client_credentials (
|
|||||||
expect_new_client_curve_bounce_fail (ctx, valid_server_public, bogus_public,
|
expect_new_client_curve_bounce_fail (ctx, valid_server_public, bogus_public,
|
||||||
bogus_secret, my_endpoint, server);
|
bogus_secret, my_endpoint, server);
|
||||||
|
|
||||||
|
int event_count = 0;
|
||||||
#ifdef ZMQ_BUILD_DRAFT_API
|
#ifdef ZMQ_BUILD_DRAFT_API
|
||||||
int event = get_monitor_event_with_timeout (server_mon, NULL, NULL, -1);
|
|
||||||
// TODO add another event type ZMQ_EVENT_HANDSHAKE_FAILED_AUTH for this case?
|
// TODO add another event type ZMQ_EVENT_HANDSHAKE_FAILED_AUTH for this case?
|
||||||
assert (
|
event_count = expect_monitor_event_multiple (
|
||||||
event
|
server_mon, ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL, EACCES);
|
||||||
== ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL); // ZAP handle the error, not curve_server
|
assert (event_count <= 1);
|
||||||
|
|
||||||
assert_no_more_monitor_events_with_timeout (server_mon, timeout);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// there may be more than one ZAP request due to repeated attempts by the client
|
// there may be more than one ZAP request due to repeated attempts by the client
|
||||||
assert (1 <= zmq_atomic_counter_value (zap_requests_handled));
|
assert (0 == event_count
|
||||||
|
|| 1 <= zmq_atomic_counter_value (zap_requests_handled));
|
||||||
}
|
}
|
||||||
|
|
||||||
void expect_zmtp_failure (void *client, char *my_endpoint, void *server, void *server_mon)
|
void expect_zmtp_failure (void *client, char *my_endpoint, void *server, void *server_mon)
|
||||||
@ -534,12 +550,9 @@ void expect_zmtp_failure (void *client, char *my_endpoint, void *server, void *s
|
|||||||
expect_bounce_fail (server, client);
|
expect_bounce_fail (server, client);
|
||||||
close_zero_linger (client);
|
close_zero_linger (client);
|
||||||
|
|
||||||
#ifdef ZMQ_BUILD_DRAFT_API
|
|
||||||
int err;
|
|
||||||
int event = get_monitor_event_with_timeout (server_mon, &err, NULL, -1);
|
|
||||||
|
|
||||||
assert (event == ZMQ_EVENT_HANDSHAKE_FAILED_ZMTP
|
#ifdef ZMQ_BUILD_DRAFT_API
|
||||||
|| (event == ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL && err == EPIPE));
|
expect_monitor_event_multiple (server_mon, ZMQ_EVENT_HANDSHAKE_FAILED_ZMTP);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
assert (0 == zmq_atomic_counter_value (zap_requests_handled));
|
assert (0 == zmq_atomic_counter_value (zap_requests_handled));
|
||||||
@ -801,13 +814,14 @@ int main (void)
|
|||||||
|
|
||||||
// ZAP non-standard cases
|
// ZAP non-standard cases
|
||||||
|
|
||||||
// status 500 internal error
|
// TODO make these observable on the client side as well (they are
|
||||||
|
// transmitted as an ERROR message)
|
||||||
|
|
||||||
|
// status 300 temporary failure
|
||||||
|
fprintf (stderr, "test_curve_security_zap_unsuccessful status 300\n");
|
||||||
setup_context_and_server_side (&ctx, &handler, &zap_thread, &server,
|
setup_context_and_server_side (&ctx, &handler, &zap_thread, &server,
|
||||||
&server_mon, my_endpoint,
|
&server_mon, my_endpoint,
|
||||||
&zap_handler_wrong_status_internal_error);
|
&zap_handler_wrong_status_temporary_failure);
|
||||||
|
|
||||||
// TODO is this usable? EAGAIN does not appear to be an appropriate error
|
|
||||||
// code, and the status text is completely lost
|
|
||||||
test_curve_security_zap_unsuccessful (ctx, my_endpoint, server, server_mon,
|
test_curve_security_zap_unsuccessful (ctx, my_endpoint, server, server_mon,
|
||||||
#ifdef ZMQ_BUILD_DRAFT_API
|
#ifdef ZMQ_BUILD_DRAFT_API
|
||||||
ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL,
|
ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL,
|
||||||
@ -819,6 +833,22 @@ int main (void)
|
|||||||
shutdown_context_and_server_side (ctx, zap_thread, server, server_mon,
|
shutdown_context_and_server_side (ctx, zap_thread, server, server_mon,
|
||||||
handler);
|
handler);
|
||||||
|
|
||||||
|
// status 500 internal error
|
||||||
|
fprintf (stderr, "test_curve_security_zap_unsuccessful status 500\n");
|
||||||
|
setup_context_and_server_side (&ctx, &handler, &zap_thread, &server,
|
||||||
|
&server_mon, my_endpoint,
|
||||||
|
&zap_handler_wrong_status_internal_error);
|
||||||
|
test_curve_security_zap_unsuccessful (ctx, my_endpoint, server, server_mon,
|
||||||
|
#ifdef ZMQ_BUILD_DRAFT_API
|
||||||
|
ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL,
|
||||||
|
EFAULT
|
||||||
|
#else
|
||||||
|
0, 0
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
shutdown_context_and_server_side (ctx, zap_thread, server, server_mon,
|
||||||
|
handler);
|
||||||
|
|
||||||
ctx = zmq_ctx_new ();
|
ctx = zmq_ctx_new ();
|
||||||
test_curve_security_invalid_keysize (ctx);
|
test_curve_security_invalid_keysize (ctx);
|
||||||
rc = zmq_ctx_term (ctx);
|
rc = zmq_ctx_term (ctx);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user