Commit 1beec5e9 authored by Martin Hurton's avatar Martin Hurton

Merge pull request #596 from hintjens/master

Problem: mechanisms are lagging behind specs
parents ba1ae7d6 76df0459
...@@ -462,7 +462,7 @@ Applicable socket types:: ZMQ_XPUB ...@@ -462,7 +462,7 @@ Applicable socket types:: ZMQ_XPUB
ZMQ_TCP_KEEPALIVE: Override SO_KEEPALIVE socket option ZMQ_TCP_KEEPALIVE: Override SO_KEEPALIVE socket option
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Override 'SO_KEEPALIVE' socket option(where supported by OS). Override 'SO_KEEPALIVE' socket option (where supported by OS).
The default value of `-1` means to skip any overrides and leave it to OS default. The default value of `-1` means to skip any overrides and leave it to OS default.
[horizontal] [horizontal]
...@@ -472,8 +472,8 @@ Default value:: -1 (leave to OS default) ...@@ -472,8 +472,8 @@ Default value:: -1 (leave to OS default)
Applicable socket types:: all, when using TCP transports. Applicable socket types:: all, when using TCP transports.
ZMQ_TCP_KEEPALIVE_IDLE: Override TCP_KEEPCNT(or TCP_KEEPALIVE on some OS) ZMQ_TCP_KEEPALIVE_IDLE: Override TCP_KEEPCNT (or TCP_KEEPALIVE on some OS)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Override 'TCP_KEEPCNT'(or 'TCP_KEEPALIVE' on some OS) socket option (where Override 'TCP_KEEPCNT'(or 'TCP_KEEPALIVE' on some OS) socket option (where
supported by OS). The default value of `-1` means to skip any overrides and supported by OS). The default value of `-1` means to skip any overrides and
...@@ -489,7 +489,7 @@ Applicable socket types:: all, when using TCP transports. ...@@ -489,7 +489,7 @@ Applicable socket types:: all, when using TCP transports.
ZMQ_TCP_KEEPALIVE_CNT: Override TCP_KEEPCNT socket option ZMQ_TCP_KEEPALIVE_CNT: Override TCP_KEEPCNT socket option
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Override 'TCP_KEEPCNT' socket option(where supported by OS). The default Override 'TCP_KEEPCNT' socket option (where supported by OS). The default
value of `-1` means to skip any overrides and leave it to OS default. value of `-1` means to skip any overrides and leave it to OS default.
[horizontal] [horizontal]
......
...@@ -138,7 +138,7 @@ int zmq::curve_client_t::encode (msg_t *msg_) ...@@ -138,7 +138,7 @@ int zmq::curve_client_t::encode (msg_t *msg_)
uint8_t *message = static_cast <uint8_t *> (msg_->data ()); uint8_t *message = static_cast <uint8_t *> (msg_->data ());
memcpy (message, "MESSAGE ", 8); memcpy (message, "MESSAGE\0", 8);
memcpy (message + 8, &cn_nonce, 8); memcpy (message + 8, &cn_nonce, 8);
memcpy (message + 16, message_box + crypto_box_BOXZEROBYTES, memcpy (message + 16, message_box + crypto_box_BOXZEROBYTES,
mlen - crypto_box_BOXZEROBYTES); mlen - crypto_box_BOXZEROBYTES);
...@@ -161,7 +161,7 @@ int zmq::curve_client_t::decode (msg_t *msg_) ...@@ -161,7 +161,7 @@ int zmq::curve_client_t::decode (msg_t *msg_)
} }
const uint8_t *message = static_cast <uint8_t *> (msg_->data ()); const uint8_t *message = static_cast <uint8_t *> (msg_->data ());
if (memcmp (message, "MESSAGE ", 8)) { if (memcmp (message, "MESSAGE\0", 8)) {
errno = EPROTO; errno = EPROTO;
return -1; return -1;
} }
...@@ -235,11 +235,11 @@ int zmq::curve_client_t::hello_msg (msg_t *msg_) ...@@ -235,11 +235,11 @@ int zmq::curve_client_t::hello_msg (msg_t *msg_)
errno_assert (rc == 0); errno_assert (rc == 0);
uint8_t *hello = static_cast <uint8_t *> (msg_->data ()); uint8_t *hello = static_cast <uint8_t *> (msg_->data ());
memcpy (hello, "HELLO ", 8); memcpy (hello, "HELLO\0", 6);
// CurveZMQ major and minor version numbers // CurveZMQ major and minor version numbers
memcpy (hello + 8, "\1\0", 2); memcpy (hello + 6, "\1\0", 2);
// Anti-amplification padding // Anti-amplification padding
memset (hello + 10, 0, 70); memset (hello + 8, 0, 72);
// Client public connection key // Client public connection key
memcpy (hello + 80, cn_public, crypto_box_PUBLICKEYBYTES); memcpy (hello + 80, cn_public, crypto_box_PUBLICKEYBYTES);
// Short nonce, prefixed by "CurveZMQHELLO---" // Short nonce, prefixed by "CurveZMQHELLO---"
...@@ -260,7 +260,7 @@ int zmq::curve_client_t::process_welcome (msg_t *msg_) ...@@ -260,7 +260,7 @@ int zmq::curve_client_t::process_welcome (msg_t *msg_)
} }
const uint8_t * welcome = static_cast <uint8_t *> (msg_->data ()); const uint8_t * welcome = static_cast <uint8_t *> (msg_->data ());
if (memcmp (welcome, "WELCOME ", 8)) { if (memcmp (welcome, "WELCOME\0", 8)) {
errno = EPROTO; errno = EPROTO;
return -1; return -1;
} }
...@@ -346,18 +346,18 @@ int zmq::curve_client_t::initiate_msg (msg_t *msg_) ...@@ -346,18 +346,18 @@ int zmq::curve_client_t::initiate_msg (msg_t *msg_)
mlen, initiate_nonce, cn_server, cn_secret); mlen, initiate_nonce, cn_server, cn_secret);
zmq_assert (rc == 0); zmq_assert (rc == 0);
rc = msg_->init_size (112 + mlen - crypto_box_BOXZEROBYTES); rc = msg_->init_size (113 + mlen - crypto_box_BOXZEROBYTES);
errno_assert (rc == 0); errno_assert (rc == 0);
uint8_t *initiate = static_cast <uint8_t *> (msg_->data ()); uint8_t *initiate = static_cast <uint8_t *> (msg_->data ());
memcpy (initiate, "INITIATE", 8); memcpy (initiate, "INITIATE\0", 9);
// Cookie provided by the server in the WELCOME command // Cookie provided by the server in the WELCOME command
memcpy (initiate + 8, cn_cookie, 96); memcpy (initiate + 9, cn_cookie, 96);
// Short nonce, prefixed by "CurveZMQINITIATE" // Short nonce, prefixed by "CurveZMQINITIATE"
memcpy (initiate + 104, &cn_nonce, 8); memcpy (initiate + 105, &cn_nonce, 8);
// Box [C + vouch + metadata](C'->S') // Box [C + vouch + metadata](C'->S')
memcpy (initiate + 112, initiate_box + crypto_box_BOXZEROBYTES, memcpy (initiate + 113, initiate_box + crypto_box_BOXZEROBYTES,
mlen - crypto_box_BOXZEROBYTES); mlen - crypto_box_BOXZEROBYTES);
cn_nonce++; cn_nonce++;
...@@ -367,18 +367,18 @@ int zmq::curve_client_t::initiate_msg (msg_t *msg_) ...@@ -367,18 +367,18 @@ int zmq::curve_client_t::initiate_msg (msg_t *msg_)
int zmq::curve_client_t::process_ready (msg_t *msg_) int zmq::curve_client_t::process_ready (msg_t *msg_)
{ {
if (msg_->size () < 32) { if (msg_->size () < 30) {
errno = EPROTO; errno = EPROTO;
return -1; return -1;
} }
const uint8_t *ready = static_cast <uint8_t *> (msg_->data ()); const uint8_t *ready = static_cast <uint8_t *> (msg_->data ());
if (memcmp (ready, "READY ", 8)) { if (memcmp (ready, "READY\0", 6)) {
errno = EPROTO; errno = EPROTO;
return -1; return -1;
} }
const size_t clen = (msg_->size () - 16) + crypto_box_BOXZEROBYTES; const size_t clen = (msg_->size () - 14) + crypto_box_BOXZEROBYTES;
uint8_t ready_nonce [crypto_box_NONCEBYTES]; uint8_t ready_nonce [crypto_box_NONCEBYTES];
uint8_t ready_plaintext [crypto_box_ZEROBYTES + 256]; uint8_t ready_plaintext [crypto_box_ZEROBYTES + 256];
...@@ -386,10 +386,10 @@ int zmq::curve_client_t::process_ready (msg_t *msg_) ...@@ -386,10 +386,10 @@ int zmq::curve_client_t::process_ready (msg_t *msg_)
memset (ready_box, 0, crypto_box_BOXZEROBYTES); memset (ready_box, 0, crypto_box_BOXZEROBYTES);
memcpy (ready_box + crypto_box_BOXZEROBYTES, memcpy (ready_box + crypto_box_BOXZEROBYTES,
ready + 16, clen - crypto_box_BOXZEROBYTES); ready + 14, clen - crypto_box_BOXZEROBYTES);
memcpy (ready_nonce, "CurveZMQREADY---", 16); memcpy (ready_nonce, "CurveZMQREADY---", 16);
memcpy (ready_nonce + 16, ready + 8, 8); memcpy (ready_nonce + 16, ready + 6, 8);
int rc = crypto_box_open_afternm (ready_plaintext, ready_box, int rc = crypto_box_open_afternm (ready_plaintext, ready_box,
clen, ready_nonce, cn_precom); clen, ready_nonce, cn_precom);
......
...@@ -141,7 +141,7 @@ int zmq::curve_server_t::encode (msg_t *msg_) ...@@ -141,7 +141,7 @@ int zmq::curve_server_t::encode (msg_t *msg_)
uint8_t *message = static_cast <uint8_t *> (msg_->data ()); uint8_t *message = static_cast <uint8_t *> (msg_->data ());
memcpy (message, "MESSAGE ", 8); memcpy (message, "MESSAGE\0", 8);
memcpy (message + 8, &cn_nonce, 8); memcpy (message + 8, &cn_nonce, 8);
memcpy (message + 16, message_box + crypto_box_BOXZEROBYTES, memcpy (message + 16, message_box + crypto_box_BOXZEROBYTES,
mlen - crypto_box_BOXZEROBYTES); mlen - crypto_box_BOXZEROBYTES);
...@@ -164,7 +164,7 @@ int zmq::curve_server_t::decode (msg_t *msg_) ...@@ -164,7 +164,7 @@ int zmq::curve_server_t::decode (msg_t *msg_)
} }
const uint8_t *message = static_cast <uint8_t *> (msg_->data ()); const uint8_t *message = static_cast <uint8_t *> (msg_->data ());
if (memcmp (message, "MESSAGE ", 8)) { if (memcmp (message, "MESSAGE\0", 8)) {
errno = EPROTO; errno = EPROTO;
return -1; return -1;
} }
...@@ -236,13 +236,13 @@ int zmq::curve_server_t::process_hello (msg_t *msg_) ...@@ -236,13 +236,13 @@ int zmq::curve_server_t::process_hello (msg_t *msg_)
} }
const uint8_t * const hello = static_cast <uint8_t *> (msg_->data ()); const uint8_t * const hello = static_cast <uint8_t *> (msg_->data ());
if (memcmp (hello, "HELLO ", 8)) { if (memcmp (hello, "HELLO\0", 6)) {
errno = EPROTO; errno = EPROTO;
return -1; return -1;
} }
const uint8_t major = hello [8]; const uint8_t major = hello [6];
const uint8_t minor = hello [9]; const uint8_t minor = hello [7];
if (major != 1 || minor != 0) { if (major != 1 || minor != 0) {
errno = EPROTO; errno = EPROTO;
...@@ -327,7 +327,7 @@ int zmq::curve_server_t::welcome_msg (msg_t *msg_) ...@@ -327,7 +327,7 @@ int zmq::curve_server_t::welcome_msg (msg_t *msg_)
errno_assert (rc == 0); errno_assert (rc == 0);
uint8_t * const welcome = static_cast <uint8_t *> (msg_->data ()); uint8_t * const welcome = static_cast <uint8_t *> (msg_->data ());
memcpy (welcome, "WELCOME ", 8); memcpy (welcome, "WELCOME\0", 8);
memcpy (welcome + 8, welcome_nonce + 8, 16); memcpy (welcome + 8, welcome_nonce + 8, 16);
memcpy (welcome + 24, welcome_ciphertext + crypto_box_BOXZEROBYTES, 144); memcpy (welcome + 24, welcome_ciphertext + crypto_box_BOXZEROBYTES, 144);
...@@ -336,13 +336,13 @@ int zmq::curve_server_t::welcome_msg (msg_t *msg_) ...@@ -336,13 +336,13 @@ int zmq::curve_server_t::welcome_msg (msg_t *msg_)
int zmq::curve_server_t::process_initiate (msg_t *msg_) int zmq::curve_server_t::process_initiate (msg_t *msg_)
{ {
if (msg_->size () < 224) { if (msg_->size () < 225) {
errno = EPROTO; errno = EPROTO;
return -1; return -1;
} }
const uint8_t *initiate = static_cast <uint8_t *> (msg_->data ()); const uint8_t *initiate = static_cast <uint8_t *> (msg_->data ());
if (memcmp (initiate, "INITIATE", 8)) { if (memcmp (initiate, "INITIATE\0", 9)) {
errno = EPROTO; errno = EPROTO;
return -1; return -1;
} }
...@@ -353,10 +353,10 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_) ...@@ -353,10 +353,10 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_)
// Open Box [C' + s'](t) // Open Box [C' + s'](t)
memset (cookie_box, 0, crypto_secretbox_BOXZEROBYTES); memset (cookie_box, 0, crypto_secretbox_BOXZEROBYTES);
memcpy (cookie_box + crypto_secretbox_BOXZEROBYTES, initiate + 24, 80); memcpy (cookie_box + crypto_secretbox_BOXZEROBYTES, initiate + 25, 80);
memcpy (cookie_nonce, "COOKIE--", 8); memcpy (cookie_nonce, "COOKIE--", 8);
memcpy (cookie_nonce + 8, initiate + 8, 16); memcpy (cookie_nonce + 8, initiate + 9, 16);
int rc = crypto_secretbox_open (cookie_plaintext, cookie_box, int rc = crypto_secretbox_open (cookie_plaintext, cookie_box,
sizeof cookie_box, sizeof cookie_box,
...@@ -375,7 +375,7 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_) ...@@ -375,7 +375,7 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_)
return -1; return -1;
} }
const size_t clen = (msg_->size () - 112) + crypto_box_BOXZEROBYTES; const size_t clen = (msg_->size () - 113) + crypto_box_BOXZEROBYTES;
uint8_t initiate_nonce [crypto_box_NONCEBYTES]; uint8_t initiate_nonce [crypto_box_NONCEBYTES];
uint8_t initiate_plaintext [crypto_box_ZEROBYTES + 96 + 256]; uint8_t initiate_plaintext [crypto_box_ZEROBYTES + 96 + 256];
...@@ -384,10 +384,10 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_) ...@@ -384,10 +384,10 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_)
// Open Box [C + vouch + metadata](C'->S') // Open Box [C + vouch + metadata](C'->S')
memset (initiate_box, 0, crypto_box_BOXZEROBYTES); memset (initiate_box, 0, crypto_box_BOXZEROBYTES);
memcpy (initiate_box + crypto_box_BOXZEROBYTES, memcpy (initiate_box + crypto_box_BOXZEROBYTES,
initiate + 112, clen - crypto_box_BOXZEROBYTES); initiate + 113, clen - crypto_box_BOXZEROBYTES);
memcpy (initiate_nonce, "CurveZMQINITIATE", 16); memcpy (initiate_nonce, "CurveZMQINITIATE", 16);
memcpy (initiate_nonce + 16, initiate + 104, 8); memcpy (initiate_nonce + 16, initiate + 105, 8);
rc = crypto_box_open (initiate_plaintext, initiate_box, rc = crypto_box_open (initiate_plaintext, initiate_box,
clen, initiate_nonce, cn_client, cn_secret); clen, initiate_nonce, cn_client, cn_secret);
...@@ -475,16 +475,16 @@ int zmq::curve_server_t::ready_msg (msg_t *msg_) ...@@ -475,16 +475,16 @@ int zmq::curve_server_t::ready_msg (msg_t *msg_)
mlen, ready_nonce, cn_precom); mlen, ready_nonce, cn_precom);
zmq_assert (rc == 0); zmq_assert (rc == 0);
rc = msg_->init_size (16 + mlen - crypto_box_BOXZEROBYTES); rc = msg_->init_size (14 + mlen - crypto_box_BOXZEROBYTES);
errno_assert (rc == 0); errno_assert (rc == 0);
uint8_t *ready = static_cast <uint8_t *> (msg_->data ()); uint8_t *ready = static_cast <uint8_t *> (msg_->data ());
memcpy (ready, "READY ", 8); memcpy (ready, "READY\0", 6);
// Short nonce, prefixed by "CurveZMQREADY---" // Short nonce, prefixed by "CurveZMQREADY---"
memcpy (ready + 8, &cn_nonce, 8); memcpy (ready + 6, &cn_nonce, 8);
// Box [metadata](S'->C') // Box [metadata](S'->C')
memcpy (ready + 16, ready_box + crypto_box_BOXZEROBYTES, memcpy (ready + 14, ready_box + crypto_box_BOXZEROBYTES,
mlen - crypto_box_BOXZEROBYTES); mlen - crypto_box_BOXZEROBYTES);
cn_nonce++; cn_nonce++;
......
...@@ -52,7 +52,7 @@ const char *zmq::mechanism_t::socket_type_string (int socket_type) const ...@@ -52,7 +52,7 @@ const char *zmq::mechanism_t::socket_type_string (int socket_type) const
static const char *names [] = {"PAIR", "PUB", "SUB", "REQ", "REP", static const char *names [] = {"PAIR", "PUB", "SUB", "REQ", "REP",
"DEALER", "ROUTER", "PULL", "PUSH", "DEALER", "ROUTER", "PULL", "PUSH",
"XPUB", "XSUB", "STREAM"}; "XPUB", "XSUB", "STREAM"};
zmq_assert (socket_type >= ZMQ_PAIR && socket_type <= ZMQ_STREAM); zmq_assert (socket_type >= 0 && socket_type <= 10);
return names [socket_type]; return names [socket_type];
} }
......
...@@ -54,8 +54,8 @@ int zmq::null_mechanism_t::next_handshake_message (msg_t *msg_) ...@@ -54,8 +54,8 @@ int zmq::null_mechanism_t::next_handshake_message (msg_t *msg_)
unsigned char *ptr = command_buffer; unsigned char *ptr = command_buffer;
// Add mechanism string // Add mechanism string
memcpy (ptr, "READY ", 8); memcpy (ptr, "READY\0", 6);
ptr += 8; ptr += 6;
// Add socket type property // Add socket type property
const char *socket_type = socket_type_string (options.type); const char *socket_type = socket_type_string (options.type);
...@@ -91,13 +91,13 @@ int zmq::null_mechanism_t::process_handshake_message (msg_t *msg_) ...@@ -91,13 +91,13 @@ int zmq::null_mechanism_t::process_handshake_message (msg_t *msg_)
static_cast <unsigned char *> (msg_->data ()); static_cast <unsigned char *> (msg_->data ());
size_t bytes_left = msg_->size (); size_t bytes_left = msg_->size ();
if (bytes_left < 8 || memcmp (ptr, "READY ", 8)) { if (bytes_left < 6 || memcmp (ptr, "READY\0", 6)) {
errno = EPROTO; errno = EPROTO;
return -1; return -1;
} }
ptr += 8; ptr += 6;
bytes_left -= 8; bytes_left -= 6;
int rc = parse_metadata (ptr, bytes_left); int rc = parse_metadata (ptr, bytes_left);
if (rc == 0) { if (rc == 0) {
......
...@@ -284,12 +284,10 @@ int zmq::options_t::setsockopt (int option_, const void *optval_, ...@@ -284,12 +284,10 @@ int zmq::options_t::setsockopt (int option_, const void *optval_,
return 0; return 0;
} }
break; break;
// If libsodium isn't installed, these options provoke EINVAL
# ifdef HAVE_LIBSODIUM
case ZMQ_CURVE_SERVER: case ZMQ_CURVE_SERVER:
# ifndef HAVE_LIBSODIUM
puts ("E: libzmq was not built using libsodium, CURVE not available");
assert (false);
# endif
if (is_int && (value == 0 || value == 1)) { if (is_int && (value == 0 || value == 1)) {
as_server = value; as_server = value;
mechanism = value? ZMQ_CURVE: ZMQ_NULL; mechanism = value? ZMQ_CURVE: ZMQ_NULL;
...@@ -298,10 +296,6 @@ int zmq::options_t::setsockopt (int option_, const void *optval_, ...@@ -298,10 +296,6 @@ int zmq::options_t::setsockopt (int option_, const void *optval_,
break; break;
case ZMQ_CURVE_PUBLICKEY: case ZMQ_CURVE_PUBLICKEY:
# ifndef HAVE_LIBSODIUM
puts ("E: libzmq was not built using libsodium, CURVE not available");
assert (false);
# endif
if (optvallen_ == CURVE_KEYSIZE) { if (optvallen_ == CURVE_KEYSIZE) {
memcpy (curve_public_key, optval_, CURVE_KEYSIZE); memcpy (curve_public_key, optval_, CURVE_KEYSIZE);
mechanism = ZMQ_CURVE; mechanism = ZMQ_CURVE;
...@@ -310,10 +304,6 @@ int zmq::options_t::setsockopt (int option_, const void *optval_, ...@@ -310,10 +304,6 @@ int zmq::options_t::setsockopt (int option_, const void *optval_,
break; break;
case ZMQ_CURVE_SECRETKEY: case ZMQ_CURVE_SECRETKEY:
# ifndef HAVE_LIBSODIUM
puts ("E: libzmq was not built using libsodium, CURVE not available");
assert (false);
# endif
if (optvallen_ == CURVE_KEYSIZE) { if (optvallen_ == CURVE_KEYSIZE) {
memcpy (curve_secret_key, optval_, CURVE_KEYSIZE); memcpy (curve_secret_key, optval_, CURVE_KEYSIZE);
mechanism = ZMQ_CURVE; mechanism = ZMQ_CURVE;
...@@ -322,10 +312,6 @@ int zmq::options_t::setsockopt (int option_, const void *optval_, ...@@ -322,10 +312,6 @@ int zmq::options_t::setsockopt (int option_, const void *optval_,
break; break;
case ZMQ_CURVE_SERVERKEY: case ZMQ_CURVE_SERVERKEY:
# ifndef HAVE_LIBSODIUM
puts ("E: libzmq was not built using libsodium, CURVE not available");
assert (false);
# endif
if (optvallen_ == CURVE_KEYSIZE) { if (optvallen_ == CURVE_KEYSIZE) {
memcpy (curve_server_key, optval_, CURVE_KEYSIZE); memcpy (curve_server_key, optval_, CURVE_KEYSIZE);
as_server = 0; as_server = 0;
...@@ -333,9 +319,7 @@ int zmq::options_t::setsockopt (int option_, const void *optval_, ...@@ -333,9 +319,7 @@ int zmq::options_t::setsockopt (int option_, const void *optval_,
return 0; return 0;
} }
break; break;
# endif
default:
break;
} }
errno = EINVAL; errno = EINVAL;
return -1; return -1;
...@@ -555,6 +539,8 @@ int zmq::options_t::getsockopt (int option_, void *optval_, size_t *optvallen_) ...@@ -555,6 +539,8 @@ int zmq::options_t::getsockopt (int option_, void *optval_, size_t *optvallen_)
} }
break; break;
// If libsodium isn't installed, these options provoke EINVAL
# ifdef HAVE_LIBSODIUM
case ZMQ_CURVE_SERVER: case ZMQ_CURVE_SERVER:
if (is_int) { if (is_int) {
*value = as_server && mechanism == ZMQ_CURVE; *value = as_server && mechanism == ZMQ_CURVE;
...@@ -582,6 +568,7 @@ int zmq::options_t::getsockopt (int option_, void *optval_, size_t *optvallen_) ...@@ -582,6 +568,7 @@ int zmq::options_t::getsockopt (int option_, void *optval_, size_t *optvallen_)
return 0; return 0;
} }
break; break;
# endif
} }
errno = EINVAL; errno = EINVAL;
return -1; return -1;
......
...@@ -295,9 +295,9 @@ int zmq::plain_mechanism_t::ready_command (msg_t *msg_) const ...@@ -295,9 +295,9 @@ int zmq::plain_mechanism_t::ready_command (msg_t *msg_) const
unsigned char *ptr = command_buffer; unsigned char *ptr = command_buffer;
// Add mechanism string // Add command name
memcpy (ptr, "READY ", 8); memcpy (ptr, "READY\0", 6);
ptr += 8; ptr += 6;
// Add socket type property // Add socket type property
const char *socket_type = socket_type_string (options.type); const char *socket_type = socket_type_string (options.type);
...@@ -325,11 +325,13 @@ int zmq::plain_mechanism_t::process_ready_command (msg_t *msg_) ...@@ -325,11 +325,13 @@ int zmq::plain_mechanism_t::process_ready_command (msg_t *msg_)
const unsigned char *ptr = static_cast <unsigned char *> (msg_->data ()); const unsigned char *ptr = static_cast <unsigned char *> (msg_->data ());
size_t bytes_left = msg_->size (); size_t bytes_left = msg_->size ();
if (bytes_left < 8 || memcmp (ptr, "READY ", 8)) { if (bytes_left < 6 || memcmp (ptr, "READY\0", 6)) {
errno = EPROTO; errno = EPROTO;
return -1; return -1;
} }
return parse_metadata (ptr + 8, bytes_left - 8); ptr += 6;
bytes_left -= 6;
return parse_metadata (ptr, bytes_left);
} }
void zmq::plain_mechanism_t::send_zap_request (const std::string &username, void zmq::plain_mechanism_t::send_zap_request (const std::string &username,
......
...@@ -106,7 +106,7 @@ const char *zmq_strerror (int errnum_) ...@@ -106,7 +106,7 @@ const char *zmq_strerror (int errnum_)
return zmq::errno_to_string (errnum_); return zmq::errno_to_string (errnum_);
} }
int zmq_errno () int zmq_errno (void)
{ {
return errno; return errno;
} }
......
...@@ -67,4 +67,4 @@ noinst_PROGRAMS += test_raw_sock ...@@ -67,4 +67,4 @@ noinst_PROGRAMS += test_raw_sock
test_raw_sock_SOURCES = test_raw_sock.cpp test_raw_sock_SOURCES = test_raw_sock.cpp
# Run the test cases # Run the test cases
TESTS = $(noinst_PROGRAMS) TESTS = $(noinst_PROGRAMS)
\ No newline at end of file
...@@ -104,7 +104,7 @@ int main (void) ...@@ -104,7 +104,7 @@ int main (void)
// Second frame contains the rest of greeting along with // Second frame contains the rest of greeting along with
// the Ready command // the Ready command
rc = zmq_recv (router, buffer, 255, 0); rc = zmq_recv (router, buffer, 255, 0);
assert (rc == 99); assert (rc == 97);
// First two bytes are major and minor version numbers. // First two bytes are major and minor version numbers.
assert (buffer [0] == 3); // ZMTP/3.0 assert (buffer [0] == 3); // ZMTP/3.0
...@@ -112,21 +112,20 @@ int main (void) ...@@ -112,21 +112,20 @@ int main (void)
// Mechanism is "NULL" // Mechanism is "NULL"
assert (memcmp (buffer + 2, "NULL\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 22) == 0); assert (memcmp (buffer + 2, "NULL\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 22) == 0);
assert (memcmp (buffer + 54, "\0\53READY ", 10) == 0); assert (memcmp (buffer + 54, "\0\51READY\0", 8) == 0);
assert (memcmp (buffer + 64, "\13Socket-Type\0\0\0\6DEALER", 22) == 0); assert (memcmp (buffer + 62, "\13Socket-Type\0\0\0\6DEALER", 22) == 0);
assert (memcmp (buffer + 86, "\10Identity\0\0\0\0", 13) == 0); assert (memcmp (buffer + 84, "\10Identity\0\0\0\0", 13) == 0);
// Announce we are ready // Announce we are ready
memcpy (buffer, "\0\53", 2); memcpy (buffer, "\0\51READY\0", 8);
memcpy (buffer + 2, "READY ", 8); memcpy (buffer + 8, "\13Socket-Type\0\0\0\6STREAM", 22);
memcpy (buffer + 10, "\13Socket-Type\0\0\0\6ROUTER", 22); memcpy (buffer + 30, "\10Identity\0\0\0\0", 13);
memcpy (buffer + 32, "\10Identity\0\0\0\0", 13);
// Send Ready command // Send Ready command
rc = zmq_msg_send (&identity, router, ZMQ_SNDMORE); rc = zmq_msg_send (&identity, router, ZMQ_SNDMORE);
assert (rc > 0); assert (rc > 0);
rc = zmq_send (router, buffer, 45, 0); rc = zmq_send (router, buffer, 43, 0);
assert (rc == 45); assert (rc == 43);
// Now we expect the data from the DEALER socket // Now we expect the data from the DEALER socket
// First frame is, again, the identity of the connection // First frame is, again, the identity of the connection
......
...@@ -19,106 +19,44 @@ ...@@ -19,106 +19,44 @@
#include <pthread.h> #include <pthread.h>
#include <string.h> #include <string.h>
#include <stdlib.h>
#include "testutil.hpp" #include "testutil.hpp"
static void * static void *
zap_handler (void *zap) zap_handler (void *zap)
{ {
int rc, more; char *version = s_recv (zap);
size_t optlen; char *sequence = s_recv (zap);
zmq_msg_t version, seqno, domain, mechanism, username, password; char *domain = s_recv (zap);
zmq_msg_t status_code, status_text, user_id; char *mechanism = s_recv (zap);
char *username = s_recv (zap);
// Version char *password = s_recv (zap);
rc = zmq_msg_init (&version);
assert (rc == 0); assert (streq (version, "1.0"));
rc = zmq_msg_recv (&version, zap, 0); assert (streq (mechanism, "PLAIN"));
assert (rc == 3 && memcmp (zmq_msg_data (&version), "1.0", 3) == 0);
optlen = sizeof more; s_sendmore (zap, version);
rc = zmq_getsockopt (zap, ZMQ_RCVMORE, &more, &optlen); s_sendmore (zap, sequence);
assert (rc == 0 && more == 1); if (streq (username, "admin")
&& streq (password, "password")) {
// Sequence number s_sendmore (zap, "200");
rc = zmq_msg_init (&seqno); s_sendmore (zap, "OK");
assert (rc == 0); s_send (zap, "anonymous");
rc = zmq_msg_recv (&seqno, zap, 0); }
assert (rc != -1); else {
optlen = sizeof more; s_sendmore (zap, "400");
rc = zmq_getsockopt (zap, ZMQ_RCVMORE, &more, &optlen); s_sendmore (zap, "Invalid username or password");
assert (rc == 0 && more == 1); s_send (zap, "");
}
// Domain
rc = zmq_msg_init (&domain); free (version);
assert (rc == 0); free (sequence);
rc = zmq_msg_recv (&domain, zap, 0); free (domain);
assert (rc != -1); free (mechanism);
optlen = sizeof more; free (username);
rc = zmq_getsockopt (zap, ZMQ_RCVMORE, &more, &optlen); free (password);
assert (rc == 0 && more == 1);
int rc = zmq_close (zap);
// Mechanism
rc = zmq_msg_init (&mechanism);
assert (rc == 0);
rc = zmq_msg_recv (&mechanism, zap, 0);
assert (rc == 5 && memcmp (zmq_msg_data (&mechanism), "PLAIN", 5) == 0);
optlen = sizeof more;
rc = zmq_getsockopt (zap, ZMQ_RCVMORE, &more, &optlen);
assert (rc == 0 && more == 1);
// Username
rc = zmq_msg_init (&username);
assert (rc == 0);
rc = zmq_msg_recv (&username, zap, 0);
bool username_ok = (rc == 5 && memcmp (zmq_msg_data (&username), "admin", 5) == 0);
optlen = sizeof more;
rc = zmq_getsockopt (zap, ZMQ_RCVMORE, &more, &optlen);
assert (rc == 0 && more == 1);
// Password
rc = zmq_msg_init (&password);
assert (rc == 0);
rc = zmq_msg_recv (&password, zap, 0);
optlen = sizeof more;
rc = zmq_getsockopt (zap, ZMQ_RCVMORE, &more, &optlen);
assert (rc == 0 && more == 0);
bool password_ok = (rc == 8 && memcmp (zmq_msg_data (&password), "password", 8) == 0);
rc = zmq_msg_send (&version, zap, ZMQ_SNDMORE);
assert (rc == 3);
rc = zmq_msg_send (&seqno, zap, ZMQ_SNDMORE);
assert (rc != -1);
rc = zmq_msg_init_size (&status_code, 3);
assert (rc == 0);
memcpy (zmq_msg_data (&status_code), username_ok && password_ok? "200": "400", 3);
rc = zmq_msg_send (&status_code, zap, ZMQ_SNDMORE);
assert (rc == 3);
rc = zmq_msg_init (&status_text);
assert (rc == 0);
rc = zmq_msg_send (&status_text, zap, ZMQ_SNDMORE);
assert (rc == 0);
rc = zmq_msg_init (&user_id);
assert (rc == 0);
rc = zmq_msg_send (&user_id, zap, 0);
assert (rc == 0);
rc = zmq_msg_close (&domain);
assert (rc == 0);
rc = zmq_msg_close (&mechanism);
assert (rc == 0);
rc = zmq_msg_close (&username);
assert (rc == 0);
rc = zmq_msg_close (&password);
assert (rc == 0);
rc = zmq_close (zap);
assert (rc == 0); assert (rc == 0);
return NULL; return NULL;
......
...@@ -20,93 +20,34 @@ ...@@ -20,93 +20,34 @@
#include "platform.hpp" #include "platform.hpp"
#include <pthread.h> #include <pthread.h>
#include <string.h> #include <string.h>
#include <stdlib.h>
#include "testutil.hpp" #include "testutil.hpp"
static void * static void *
zap_handler (void *zap) zap_handler (void *zap)
{ {
int rc, more; char *version = s_recv (zap);
size_t optlen; char *sequence = s_recv (zap);
zmq_msg_t version, seqno, domain, mechanism, key; char *domain = s_recv (zap);
zmq_msg_t status_code, status_text, user_id; char *mechanism = s_recv (zap);
char *client_key = s_recv (zap);
// Version
rc = zmq_msg_init (&version); assert (streq (version, "1.0"));
assert (rc == 0); assert (streq (mechanism, "CURVE"));
rc = zmq_msg_recv (&version, zap, 0);
assert (rc == 3 && memcmp (zmq_msg_data (&version), "1.0", 3) == 0); s_sendmore (zap, version);
optlen = sizeof more; s_sendmore (zap, sequence);
rc = zmq_getsockopt (zap, ZMQ_RCVMORE, &more, &optlen); s_sendmore (zap, "200");
assert (rc == 0 && more == 1); s_sendmore (zap, "OK");
s_send (zap, "anonymous");
// Sequence number
rc = zmq_msg_init (&seqno); free (version);
assert (rc == 0); free (sequence);
rc = zmq_msg_recv (&seqno, zap, 0); free (domain);
assert (rc != -1); free (mechanism);
optlen = sizeof more; free (client_key);
rc = zmq_getsockopt (zap, ZMQ_RCVMORE, &more, &optlen);
assert (rc == 0 && more == 1);
// Domain
rc = zmq_msg_init (&domain);
assert (rc == 0);
rc = zmq_msg_recv (&domain, zap, 0);
assert (rc != -1);
optlen = sizeof more;
rc = zmq_getsockopt (zap, ZMQ_RCVMORE, &more, &optlen);
assert (rc == 0 && more == 1);
// Mechanism
rc = zmq_msg_init (&mechanism);
assert (rc == 0);
rc = zmq_msg_recv (&mechanism, zap, 0);
assert (rc == 5 && memcmp (zmq_msg_data (&mechanism), "CURVE", 5) == 0);
optlen = sizeof more;
rc = zmq_getsockopt (zap, ZMQ_RCVMORE, &more, &optlen);
assert (rc == 0 && more == 1);
// Key
rc = zmq_msg_init (&key);
assert (rc == 0);
rc = zmq_msg_recv (&key, zap, 0);
optlen = sizeof more;
rc = zmq_getsockopt (zap, ZMQ_RCVMORE, &more, &optlen);
assert (rc == 0 && more == 0);
// Send response
rc = zmq_msg_send (&version, zap, ZMQ_SNDMORE);
assert (rc == 3);
rc = zmq_msg_send (&seqno, zap, ZMQ_SNDMORE);
assert (rc != -1);
rc = zmq_msg_init_size (&status_code, 3);
assert (rc == 0);
memcpy (zmq_msg_data (&status_code), "200", 3);
rc = zmq_msg_send (&status_code, zap, ZMQ_SNDMORE);
assert (rc == 3);
rc = zmq_msg_init (&status_text);
assert (rc == 0);
rc = zmq_msg_send (&status_text, zap, ZMQ_SNDMORE);
assert (rc == 0);
rc = zmq_msg_init (&user_id);
assert (rc == 0);
rc = zmq_msg_send (&user_id, zap, 0);
assert (rc == 0);
rc = zmq_msg_close (&domain);
assert (rc == 0);
rc = zmq_msg_close (&mechanism);
assert (rc == 0);
rc = zmq_msg_close (&key);
assert (rc == 0);
rc = zmq_close (zap); int rc = zmq_close (zap);
assert (rc == 0); assert (rc == 0);
return NULL; return NULL;
...@@ -115,7 +56,7 @@ zap_handler (void *zap) ...@@ -115,7 +56,7 @@ zap_handler (void *zap)
int main (void) int main (void)
{ {
#ifndef HAVE_LIBSODIUM #ifndef HAVE_LIBSODIUM
printf("Libsodium not availabile - skipping test.\n"); printf("libsodium not installed, skipping CURVE test\n");
return 0; return 0;
#endif #endif
int rc; int rc;
......
...@@ -101,7 +101,7 @@ test_stream_to_dealer (void) ...@@ -101,7 +101,7 @@ test_stream_to_dealer (void)
// Second frame contains the rest of greeting along with // Second frame contains the rest of greeting along with
// the Ready command // the Ready command
rc = zmq_recv (stream, buffer, 255, 0); rc = zmq_recv (stream, buffer, 255, 0);
assert (rc == 99); assert (rc == 97);
// First two bytes are major and minor version numbers. // First two bytes are major and minor version numbers.
assert (buffer [0] == 3); // ZMTP/3.0 assert (buffer [0] == 3); // ZMTP/3.0
...@@ -109,21 +109,20 @@ test_stream_to_dealer (void) ...@@ -109,21 +109,20 @@ test_stream_to_dealer (void)
// Mechanism is "NULL" // Mechanism is "NULL"
assert (memcmp (buffer + 2, "NULL\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 22) == 0); assert (memcmp (buffer + 2, "NULL\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 22) == 0);
assert (memcmp (buffer + 54, "\0\53READY ", 10) == 0); assert (memcmp (buffer + 54, "\0\51READY\0", 8) == 0);
assert (memcmp (buffer + 64, "\13Socket-Type\0\0\0\6DEALER", 22) == 0); assert (memcmp (buffer + 62, "\13Socket-Type\0\0\0\6DEALER", 22) == 0);
assert (memcmp (buffer + 86, "\10Identity\0\0\0\0", 13) == 0); assert (memcmp (buffer + 84, "\10Identity\0\0\0\0", 13) == 0);
// Announce we are ready // Announce we are ready
memcpy (buffer, "\0\53", 2); memcpy (buffer, "\0\51READY\0", 8);
memcpy (buffer + 2, "READY ", 8); memcpy (buffer + 8, "\13Socket-Type\0\0\0\6STREAM", 22);
memcpy (buffer + 10, "\13Socket-Type\0\0\0\6STREAM", 22); memcpy (buffer + 30, "\10Identity\0\0\0\0", 13);
memcpy (buffer + 32, "\10Identity\0\0\0\0", 13);
// Send Ready command // Send Ready command
rc = zmq_msg_send (&identity, stream, ZMQ_SNDMORE); rc = zmq_msg_send (&identity, stream, ZMQ_SNDMORE);
assert (rc > 0); assert (rc > 0);
rc = zmq_send (stream, buffer, 45, 0); rc = zmq_send (stream, buffer, 43, 0);
assert (rc == 45); assert (rc == 43);
// Now we expect the data from the DEALER socket // Now we expect the data from the DEALER socket
// First frame is, again, the identity of the connection // First frame is, again, the identity of the connection
......
...@@ -76,4 +76,36 @@ bounce (void *server, void *client) ...@@ -76,4 +76,36 @@ bounce (void *server, void *client)
assert (memcmp (buffer, content, 32) == 0); assert (memcmp (buffer, content, 32) == 0);
} }
// Receive 0MQ string from socket and convert into C string
// Caller must free returned string. Returns NULL if the context
// is being terminated.
char *
s_recv (void *socket) {
char buffer [256];
int size = zmq_recv (socket, buffer, 255, 0);
if (size == -1)
return NULL;
if (size > 255)
size = 255;
buffer [size] = 0;
return strdup (buffer);
}
// Convert C string to 0MQ string and send to socket
int
s_send (void *socket, const char *string) {
int size = zmq_send (socket, string, strlen (string), 0);
return size;
}
// Sends string as 0MQ string, as multipart non-terminal
int
s_sendmore (void *socket, const char *string) {
int size = zmq_send (socket, string, strlen (string), ZMQ_SNDMORE);
return size;
}
#define streq(s1,s2) (!strcmp ((s1), (s2)))
#define strneq(s1,s2) (strcmp ((s1), (s2)))
#endif #endif
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