Skip to content

Commit

Permalink
Updated security mechanisms to use variable-length commands
Browse files Browse the repository at this point in the history
RFC23, RFC24, RFC26 now use variable-length command names that
end in null octet (valid C strings) instead of fixed-length
space padded strings.
  • Loading branch information
hintjens committed Jun 28, 2013
1 parent dd14d4e commit 7832add
Show file tree
Hide file tree
Showing 11 changed files with 153 additions and 242 deletions.
32 changes: 16 additions & 16 deletions src/curve_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ int zmq::curve_client_t::encode (msg_t *msg_)

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 + 16, message_box + crypto_box_BOXZEROBYTES,
mlen - crypto_box_BOXZEROBYTES);
Expand All @@ -161,7 +161,7 @@ int zmq::curve_client_t::decode (msg_t *msg_)
}

const uint8_t *message = static_cast <uint8_t *> (msg_->data ());
if (memcmp (message, "MESSAGE ", 8)) {
if (memcmp (message, "MESSAGE\0", 8)) {
errno = EPROTO;
return -1;
}
Expand Down Expand Up @@ -235,11 +235,11 @@ int zmq::curve_client_t::hello_msg (msg_t *msg_)
errno_assert (rc == 0);
uint8_t *hello = static_cast <uint8_t *> (msg_->data ());

memcpy (hello, "HELLO ", 8);
memcpy (hello, "HELLO\0", 6);
// CurveZMQ major and minor version numbers
memcpy (hello + 8, "\1\0", 2);
memcpy (hello + 6, "\1\0", 2);
// Anti-amplification padding
memset (hello + 10, 0, 70);
memset (hello + 8, 0, 72);
// Client public connection key
memcpy (hello + 80, cn_public, crypto_box_PUBLICKEYBYTES);
// Short nonce, prefixed by "CurveZMQHELLO---"
Expand All @@ -260,7 +260,7 @@ int zmq::curve_client_t::process_welcome (msg_t *msg_)
}

const uint8_t * welcome = static_cast <uint8_t *> (msg_->data ());
if (memcmp (welcome, "WELCOME ", 8)) {
if (memcmp (welcome, "WELCOME\0", 8)) {
errno = EPROTO;
return -1;
}
Expand Down Expand Up @@ -346,18 +346,18 @@ int zmq::curve_client_t::initiate_msg (msg_t *msg_)
mlen, initiate_nonce, cn_server, cn_secret);
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);

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
memcpy (initiate + 8, cn_cookie, 96);
memcpy (initiate + 9, cn_cookie, 96);
// Short nonce, prefixed by "CurveZMQINITIATE"
memcpy (initiate + 104, &cn_nonce, 8);
memcpy (initiate + 105, &cn_nonce, 8);
// 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);

cn_nonce++;
Expand All @@ -367,29 +367,29 @@ int zmq::curve_client_t::initiate_msg (msg_t *msg_)

int zmq::curve_client_t::process_ready (msg_t *msg_)
{
if (msg_->size () < 32) {
if (msg_->size () < 30) {
errno = EPROTO;
return -1;
}

const uint8_t *ready = static_cast <uint8_t *> (msg_->data ());
if (memcmp (ready, "READY ", 8)) {
if (memcmp (ready, "READY\0", 6)) {
errno = EPROTO;
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_plaintext [crypto_box_ZEROBYTES + 256];
uint8_t ready_box [crypto_box_BOXZEROBYTES + 16 + 256];

memset (ready_box, 0, 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 + 16, ready + 8, 8);
memcpy (ready_nonce + 16, ready + 6, 8);

int rc = crypto_box_open_afternm (ready_plaintext, ready_box,
clen, ready_nonce, cn_precom);
Expand Down
34 changes: 17 additions & 17 deletions src/curve_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ int zmq::curve_server_t::encode (msg_t *msg_)

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 + 16, message_box + crypto_box_BOXZEROBYTES,
mlen - crypto_box_BOXZEROBYTES);
Expand All @@ -164,7 +164,7 @@ int zmq::curve_server_t::decode (msg_t *msg_)
}

const uint8_t *message = static_cast <uint8_t *> (msg_->data ());
if (memcmp (message, "MESSAGE ", 8)) {
if (memcmp (message, "MESSAGE\0", 8)) {
errno = EPROTO;
return -1;
}
Expand Down Expand Up @@ -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 ());
if (memcmp (hello, "HELLO ", 8)) {
if (memcmp (hello, "HELLO\0", 6)) {
errno = EPROTO;
return -1;
}

const uint8_t major = hello [8];
const uint8_t minor = hello [9];
const uint8_t major = hello [6];
const uint8_t minor = hello [7];

if (major != 1 || minor != 0) {
errno = EPROTO;
Expand Down Expand Up @@ -327,7 +327,7 @@ int zmq::curve_server_t::welcome_msg (msg_t *msg_)
errno_assert (rc == 0);

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 + 24, welcome_ciphertext + crypto_box_BOXZEROBYTES, 144);

Expand All @@ -336,13 +336,13 @@ int zmq::curve_server_t::welcome_msg (msg_t *msg_)

int zmq::curve_server_t::process_initiate (msg_t *msg_)
{
if (msg_->size () < 224) {
if (msg_->size () < 225) {
errno = EPROTO;
return -1;
}

const uint8_t *initiate = static_cast <uint8_t *> (msg_->data ());
if (memcmp (initiate, "INITIATE", 8)) {
if (memcmp (initiate, "INITIATE\0", 9)) {
errno = EPROTO;
return -1;
}
Expand All @@ -353,10 +353,10 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_)

// Open Box [C' + s'](t)
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 + 8, initiate + 8, 16);
memcpy (cookie_nonce + 8, initiate + 9, 16);

int rc = crypto_secretbox_open (cookie_plaintext, cookie_box,
sizeof cookie_box,
Expand All @@ -375,7 +375,7 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_)
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_plaintext [crypto_box_ZEROBYTES + 96 + 256];
Expand All @@ -384,10 +384,10 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_)
// Open Box [C + vouch + metadata](C'->S')
memset (initiate_box, 0, 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 + 16, initiate + 104, 8);
memcpy (initiate_nonce + 16, initiate + 105, 8);

rc = crypto_box_open (initiate_plaintext, initiate_box,
clen, initiate_nonce, cn_client, cn_secret);
Expand Down Expand Up @@ -475,16 +475,16 @@ int zmq::curve_server_t::ready_msg (msg_t *msg_)
mlen, ready_nonce, cn_precom);
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);

uint8_t *ready = static_cast <uint8_t *> (msg_->data ());

memcpy (ready, "READY ", 8);
memcpy (ready, "READY\0", 6);
// Short nonce, prefixed by "CurveZMQREADY---"
memcpy (ready + 8, &cn_nonce, 8);
memcpy (ready + 6, &cn_nonce, 8);
// Box [metadata](S'->C')
memcpy (ready + 16, ready_box + crypto_box_BOXZEROBYTES,
memcpy (ready + 14, ready_box + crypto_box_BOXZEROBYTES,
mlen - crypto_box_BOXZEROBYTES);

cn_nonce++;
Expand Down
2 changes: 1 addition & 1 deletion src/mechanism.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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",
"DEALER", "ROUTER", "PULL", "PUSH",
"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];
}

Expand Down
10 changes: 5 additions & 5 deletions src/null_mechanism.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ int zmq::null_mechanism_t::next_handshake_message (msg_t *msg_)
unsigned char *ptr = command_buffer;

// Add mechanism string
memcpy (ptr, "READY ", 8);
ptr += 8;
memcpy (ptr, "READY\0", 6);
ptr += 6;

// Add socket type property
const char *socket_type = socket_type_string (options.type);
Expand Down Expand Up @@ -91,13 +91,13 @@ int zmq::null_mechanism_t::process_handshake_message (msg_t *msg_)
static_cast <unsigned char *> (msg_->data ());
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;
return -1;
}

ptr += 8;
bytes_left -= 8;
ptr += 6;
bytes_left -= 6;

int rc = parse_metadata (ptr, bytes_left);
if (rc == 0) {
Expand Down
12 changes: 7 additions & 5 deletions src/plain_mechanism.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,9 +295,9 @@ int zmq::plain_mechanism_t::ready_command (msg_t *msg_) const

unsigned char *ptr = command_buffer;

// Add mechanism string
memcpy (ptr, "READY ", 8);
ptr += 8;
// Add command name
memcpy (ptr, "READY\0", 6);
ptr += 6;

// Add socket type property
const char *socket_type = socket_type_string (options.type);
Expand Down Expand Up @@ -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 ());
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;
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,
Expand Down
2 changes: 1 addition & 1 deletion tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,4 @@ noinst_PROGRAMS += test_raw_sock
test_raw_sock_SOURCES = test_raw_sock.cpp

# Run the test cases
TESTS = $(noinst_PROGRAMS)
TESTS = $(noinst_PROGRAMS)
19 changes: 9 additions & 10 deletions tests/test_raw_sock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,29 +104,28 @@ int main (void)
// Second frame contains the rest of greeting along with
// the Ready command
rc = zmq_recv (router, buffer, 255, 0);
assert (rc == 99);
assert (rc == 97);

// First two bytes are major and minor version numbers.
assert (buffer [0] == 3); // ZMTP/3.0
assert (buffer [1] == 0);

// 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 + 54, "\0\53READY ", 10) == 0);
assert (memcmp (buffer + 64, "\13Socket-Type\0\0\0\6DEALER", 22) == 0);
assert (memcmp (buffer + 86, "\10Identity\0\0\0\0", 13) == 0);
assert (memcmp (buffer + 54, "\0\51READY\0", 8) == 0);
assert (memcmp (buffer + 62, "\13Socket-Type\0\0\0\6DEALER", 22) == 0);
assert (memcmp (buffer + 84, "\10Identity\0\0\0\0", 13) == 0);

// Announce we are ready
memcpy (buffer, "\0\53", 2);
memcpy (buffer + 2, "READY ", 8);
memcpy (buffer + 10, "\13Socket-Type\0\0\0\6ROUTER", 22);
memcpy (buffer + 32, "\10Identity\0\0\0\0", 13);
memcpy (buffer, "\0\51READY\0", 8);
memcpy (buffer + 8, "\13Socket-Type\0\0\0\6STREAM", 22);
memcpy (buffer + 30, "\10Identity\0\0\0\0", 13);

// Send Ready command
rc = zmq_msg_send (&identity, router, ZMQ_SNDMORE);
assert (rc > 0);
rc = zmq_send (router, buffer, 45, 0);
assert (rc == 45);
rc = zmq_send (router, buffer, 43, 0);
assert (rc == 43);

// Now we expect the data from the DEALER socket
// First frame is, again, the identity of the connection
Expand Down
Loading

0 comments on commit 7832add

Please sign in to comment.