libzmq/src/mechanism.hpp

154 lines
5.0 KiB
C++
Raw Normal View History

2013-05-13 22:34:27 +02:00
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
2013-05-13 22:34:27 +02:00
This file is part of libzmq, the ZeroMQ core engine in C++.
2013-05-13 22:34:27 +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-05-13 22:34:27 +02:00
(at your option) any later version.
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-05-13 22:34:27 +02: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/>.
*/
#ifndef __ZMQ_MECHANISM_HPP_INCLUDED__
#define __ZMQ_MECHANISM_HPP_INCLUDED__
#include "stdint.hpp"
2013-05-13 22:34:27 +02:00
#include "options.hpp"
#include "blob.hpp"
2014-04-30 14:17:38 +02:00
#include "metadata.hpp"
2013-05-13 22:34:27 +02:00
namespace zmq
{
// Abstract class representing security mechanism.
2015-09-06 18:46:32 +02:00
// Different mechanism extends this class.
2013-05-13 22:34:27 +02:00
class msg_t;
class mechanism_t
{
public:
enum status_t {
handshaking,
ready,
error
};
Replace console output by monitoring events for curve security issues (#2645) * Fixing #2002 one way of doing it * Mechanisms can implement a new method `error_detail()` * This error detail have three values for the moment: no_detail (default), protocol, encryption. + generic enough to make sense for all mechanisms. - low granularity level on information. * Fixing #2002: implementation of the error details The ZMQ_EVENT_HANDSHAKE_FAILED event carries the error details as value. * Removed Microsoft extenstion for enum member access This was leading to compilation error under linux. * Adaptation of CURVE test cases * Monitoring event: changed API for detailed events Removed ZMQ_EVENT_HANDSHAKE_FAILED and replaced it by: - ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL, - ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL, - ZMQ_EVENT_HANDSHAKE_FAILED_ENCRYPTION Adaptation of text case `security_curve` * Removed event value comparison This was introduced for the previous API model adaptation * Removed the prints in std output and added missing details `current_error_detail` was not set in every protocol error cases * Fixed initialization of current_error_detail * Fixed error in greeting test case The handshake failure due to mechanism mismatch in greeting is actually a protocol error. The error handling method consider it like so and send a protocol handshake failure monitoring event instead of no_detail. Fixed the test_security_curve expectation as well. * Upgraded tests of monitoring events The tests check the number of monitoring events received * Problem: does not build under Linux or without ZMQ_DRAFT_API Solution: - properly use ZMQ_DRAFT_API conditional compilation - use receive timeouts instead of Sleep * Problem: duplicate definition of variable 'timeout' Solution: merged definitions * Problem: inconsistent timing dependencies Solution: reduce timing dependency by using timeouts at more places * Problem: assertion failure under Linux due to unexpected monitor event Solution: output event type to aid debugging * Problem: erroneous assertion code * Problem: assertion failure with a garbage server key due to an extra third event Solution: changed assertion to expect three events (needs to be checked) * Problem: extra include directive to non-existent file Solution: removed include directive * Problem: assertion failure on appveyor for unknown reason Solution: improve debug output * Problem: no build with libsodium and draft api Solution: add build configurations with libsodium and draft api * Problem: assertion failure on CI Solution: change assertion to reflect actual behaviour on CI (at least temporarily) * Problem: error in condition in assertion code * Problem: assertion failure on CI Solution: generalize assertion to match behavior on CI * Problem: assertion failures on CI Solution: removed inconsistent assertion on no monitor events before flushing improved debuggability by converting function into macro * Problem: diverging test code for three analogous test cases with garbage key Solution: extract common code into function * Problem: does not build without ZMQ_BUILD_DRAFT_API Solution: introduce dummy variable * Attempt to remove workaround regarding ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL again * Problem: EAGAIN error after handshake complete if there is no more data in inbuffer Solution: Skip tcp_read attempt in that case * Problem: handshaking event emitted after handshaking failed Solution: use stream_engine_t::handshaking instead of mechanism_t::status() to determine whether still handshaking * Include error code in debug output * Improve debugging output: output flushed events * Split up ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL into ZMQ_EVENT_HANDSHAKE_FAILED_ZMTP and ZMQ_EVENT_HANDSHAKE_FAILED_ZAP * Fixed compilation without ZMQ_BUILD_DRAFT_API * Renamed ZMQ_EVENT_HANDSHAKE_SUCCEED to ZMQ_EVENT_HANDSHAKE_SUCCEEDED for language consistency * Renamed ZMQ_EVENT_HANDSHAKE_SUCCEED to ZMQ_EVENT_HANDSHAKE_SUCCEEDED for language consistency * Renamed ZMQ_EVENT_HANDSHAKE_SUCCEED to ZMQ_EVENT_HANDSHAKE_SUCCEEDED for language consistency * Fixed assert_monitor_event (require event instead of allowing no event) Reverted erroneous change to handshaking condition Renamed test_wrong_key to test_garbage_key Generalized assumption in test_garbage_key to allow for ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL with error == EPIPE * Better isolate test cases from each other by providing a fresh context & server for each * Added diagnostic output * Changed assertion to reflect actual behavior on CI * Fixed formatting, observe maximum line length * Fixed formatting, observe maximum line length * Increase timeout to check if this fixes valgrind run * Close server with close_zero_linger * Increase timeout to check if this fixes valgrind run * Increase timeout to check if this fixes valgrind run * Generalize assertion to also work with valgrind * Fixed formatting * Add more diagnostic output * Generalize assertion to also work with valgrind
2017-08-03 15:15:56 +02:00
// Provides more details when in status_t::error
enum error_detail_t {
no_detail,
zmtp,
zap,
encryption
};
2013-05-13 22:34:27 +02:00
mechanism_t (const options_t &options_);
virtual ~mechanism_t ();
// Prepare next handshake command that is to be sent to the peer.
virtual int next_handshake_command (msg_t *msg_) = 0;
2013-05-13 22:34:27 +02:00
// Process the handshake command received from the peer.
virtual int process_handshake_command (msg_t *msg_) = 0;
2013-05-13 22:34:27 +02:00
virtual int encode (msg_t *) { return 0; }
virtual int decode (msg_t *) { return 0; }
// Notifies mechanism about availability of ZAP message.
virtual int zap_msg_available () { return 0; }
// Returns the status of this mechanism.
virtual status_t status () const = 0;
2013-05-13 22:34:27 +02:00
Replace console output by monitoring events for curve security issues (#2645) * Fixing #2002 one way of doing it * Mechanisms can implement a new method `error_detail()` * This error detail have three values for the moment: no_detail (default), protocol, encryption. + generic enough to make sense for all mechanisms. - low granularity level on information. * Fixing #2002: implementation of the error details The ZMQ_EVENT_HANDSHAKE_FAILED event carries the error details as value. * Removed Microsoft extenstion for enum member access This was leading to compilation error under linux. * Adaptation of CURVE test cases * Monitoring event: changed API for detailed events Removed ZMQ_EVENT_HANDSHAKE_FAILED and replaced it by: - ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL, - ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL, - ZMQ_EVENT_HANDSHAKE_FAILED_ENCRYPTION Adaptation of text case `security_curve` * Removed event value comparison This was introduced for the previous API model adaptation * Removed the prints in std output and added missing details `current_error_detail` was not set in every protocol error cases * Fixed initialization of current_error_detail * Fixed error in greeting test case The handshake failure due to mechanism mismatch in greeting is actually a protocol error. The error handling method consider it like so and send a protocol handshake failure monitoring event instead of no_detail. Fixed the test_security_curve expectation as well. * Upgraded tests of monitoring events The tests check the number of monitoring events received * Problem: does not build under Linux or without ZMQ_DRAFT_API Solution: - properly use ZMQ_DRAFT_API conditional compilation - use receive timeouts instead of Sleep * Problem: duplicate definition of variable 'timeout' Solution: merged definitions * Problem: inconsistent timing dependencies Solution: reduce timing dependency by using timeouts at more places * Problem: assertion failure under Linux due to unexpected monitor event Solution: output event type to aid debugging * Problem: erroneous assertion code * Problem: assertion failure with a garbage server key due to an extra third event Solution: changed assertion to expect three events (needs to be checked) * Problem: extra include directive to non-existent file Solution: removed include directive * Problem: assertion failure on appveyor for unknown reason Solution: improve debug output * Problem: no build with libsodium and draft api Solution: add build configurations with libsodium and draft api * Problem: assertion failure on CI Solution: change assertion to reflect actual behaviour on CI (at least temporarily) * Problem: error in condition in assertion code * Problem: assertion failure on CI Solution: generalize assertion to match behavior on CI * Problem: assertion failures on CI Solution: removed inconsistent assertion on no monitor events before flushing improved debuggability by converting function into macro * Problem: diverging test code for three analogous test cases with garbage key Solution: extract common code into function * Problem: does not build without ZMQ_BUILD_DRAFT_API Solution: introduce dummy variable * Attempt to remove workaround regarding ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL again * Problem: EAGAIN error after handshake complete if there is no more data in inbuffer Solution: Skip tcp_read attempt in that case * Problem: handshaking event emitted after handshaking failed Solution: use stream_engine_t::handshaking instead of mechanism_t::status() to determine whether still handshaking * Include error code in debug output * Improve debugging output: output flushed events * Split up ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL into ZMQ_EVENT_HANDSHAKE_FAILED_ZMTP and ZMQ_EVENT_HANDSHAKE_FAILED_ZAP * Fixed compilation without ZMQ_BUILD_DRAFT_API * Renamed ZMQ_EVENT_HANDSHAKE_SUCCEED to ZMQ_EVENT_HANDSHAKE_SUCCEEDED for language consistency * Renamed ZMQ_EVENT_HANDSHAKE_SUCCEED to ZMQ_EVENT_HANDSHAKE_SUCCEEDED for language consistency * Renamed ZMQ_EVENT_HANDSHAKE_SUCCEED to ZMQ_EVENT_HANDSHAKE_SUCCEEDED for language consistency * Fixed assert_monitor_event (require event instead of allowing no event) Reverted erroneous change to handshaking condition Renamed test_wrong_key to test_garbage_key Generalized assumption in test_garbage_key to allow for ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL with error == EPIPE * Better isolate test cases from each other by providing a fresh context & server for each * Added diagnostic output * Changed assertion to reflect actual behavior on CI * Fixed formatting, observe maximum line length * Fixed formatting, observe maximum line length * Increase timeout to check if this fixes valgrind run * Close server with close_zero_linger * Increase timeout to check if this fixes valgrind run * Increase timeout to check if this fixes valgrind run * Generalize assertion to also work with valgrind * Fixed formatting * Add more diagnostic output * Generalize assertion to also work with valgrind
2017-08-03 15:15:56 +02:00
// Returns details about of the current error of the mechanism.
// Returned value does not makes sense if the current status is not error.
virtual error_detail_t error_detail () const { return no_detail; }
2013-05-13 22:34:27 +02:00
void set_peer_identity (const void *id_ptr, size_t id_size);
void peer_identity (msg_t *msg_);
void set_user_id (const void *user_id, size_t size);
blob_t get_user_id () const;
const metadata_t::dict_t& get_zmtp_properties () {
return zmtp_properties;
}
const metadata_t::dict_t& get_zap_properties () {
return zap_properties;
}
2014-04-30 14:17:38 +02:00
2013-05-13 22:34:27 +02:00
protected:
// Only used to identify the socket for the Socket-Type
// property in the wire protocol.
2013-05-13 22:34:27 +02:00
const char *socket_type_string (int socket_type) const;
[WIP, do not merge] Problem: insufficient tests for ZMTP-CURVE protocol errors (#2680) * Extracted connect_vanilla_socket function * Problem: no tests for ZMTP-CURVE protocol errors Solution: added two test cases with erroneous HELLO commands * Problem: insufficient tests for ZMTP-CURVE protocol errors Solution: added two test cases with erroneous HELLO command version * Problem: test HELLO message is invalid apart from deliberate errors Solution: create cryptographically correct HELLO message add tweetnacl.c to test_security_curve * Problem: nonce is incorrect, build fails with GCC Solution: use correct non prefix * Problem: make builds are failing Solution: transfer CMake changes to (auto)make files * Problem: nonce is incorrect, build fails with GCC Solution: use correct non prefix * Problem: make builds are failing Solution: transfer CMake changes to (auto)make files * Problem: no test with INITIATE command with invalid length Solution: added test case * Problem: code duplication between test_security_curve.cpp and curve_client.cpp Solution: extracted parts of zmq::curve_client_t::produce_hello into reusable function * Problem: code duplication between test_security_curve.cpp and curve_client.cpp Solution: extracted further parts of zmq::curve_client_t into reusable functions added missing file * Problem: mechanism_t::add_property can be declared static Solution: declare mechanism_t::add_property static * Problem: intermediate crypto data needs to be passed between static function calls to curve_client_tools_t Solution: add non-static member functions * Problem: msg_t instance may be closed twice Solution: remove offending close * Problem: prepare_hello uses static curve_client_tools_t::produce_hello Solution: Use non-static curve_client_tools_t::produce_hello * Problem: no test with invalid command name where INITIATE command is expected Solution: added test case * Problem: make builds are failing due to curve_client_tools.hpp not being found Solution: add curve_client_tools.hpp to list of source files * Problem: wrong initializer order in zmq::curve_client_t Solution: reorder * Problem: under non-Windows systems, test fails because random_open was not called Solution: call random_open/random_close within test * Problem: conflict between custom function htonll and macro definition on Darwin Solution: define htonll function only if not defined as a macro * Problem: nullptr not defined on all platforms Solution: replace nullptr by NULL * Problem: libsodium builds not working Solution: adapt compile and link file sets for libsodium builds * Problem: Makefile.am broken Solution: Fix syntax * Problem: no tests for garbage encrypted cookie or content in INITIATE Solution: added test cases * Problem: test cases accidentally excluded from build Solution: remove #if/#endif * Solution: some error cases are unreachable Problem: for the time being, added some comments without changing the code * Added comments on hard-to-test cases
2017-08-15 16:28:24 +02:00
static size_t add_property (unsigned char *ptr,
const char *name,
const void *value,
size_t value_len);
2013-05-13 22:34:27 +02:00
// Parses a metadata.
// Metadata consists of a list of properties consisting of
// name and value as size-specified strings.
// Returns 0 on success and -1 on error, in which case errno is set.
2014-04-30 14:17:38 +02:00
int parse_metadata (
const unsigned char *ptr_, size_t length, bool zap_flag = false);
2013-06-22 19:02:08 +02:00
// This is called by parse_property method whenever it
// parses a new property. The function should return 0
// on success and -1 on error, in which case it should
// set errno. Signaling error prevents parser from
2013-06-22 19:02:08 +02:00
// parsing remaining data.
// Derived classes are supposed to override this
// method to handle custom processing.
virtual int property (const std::string& name_,
2013-06-22 19:02:08 +02:00
const void *value_, size_t length_);
// Properties received from ZMTP peer.
metadata_t::dict_t zmtp_properties;
// Properties received from ZAP server.
metadata_t::dict_t zap_properties;
2014-04-30 14:17:38 +02:00
2013-05-13 22:34:27 +02:00
options_t options;
private:
blob_t identity;
blob_t user_id;
// Returns true iff socket associated with the mechanism
// is compatible with a given socket type 'type_'.
bool check_socket_type (const std::string& type_) const;
2013-05-13 22:34:27 +02:00
};
}
#endif