mirror of
https://github.com/zeromq/libzmq.git
synced 2025-10-30 21:50:49 +01:00
Problem: ZMQ_CURVE_SECRETKEY reads beyond end of Z85 data
Solution: change setsockopts on printable keys to expect 41, nor 40 bytes. Code still accepts 40 bytes for compatibility, and copies the key to a well-terminated string before using it. Fixes #1148
This commit is contained in:
@@ -85,6 +85,8 @@ ZMQ_CURVE_SECRETKEY: Retrieve current CURVE secret key
|
|||||||
Retrieves the current long term secret key for the socket. You can
|
Retrieves the current long term secret key for the socket. You can
|
||||||
provide either a 32 byte buffer, to retrieve the binary key value, or
|
provide either a 32 byte buffer, to retrieve the binary key value, or
|
||||||
a 41 byte buffer, to retrieve the key in a printable Z85 format.
|
a 41 byte buffer, to retrieve the key in a printable Z85 format.
|
||||||
|
NOTE: to fetch a printable key, the buffer must be 41 bytes large
|
||||||
|
to hold the 40-char key value and one null byte.
|
||||||
|
|
||||||
[horizontal]
|
[horizontal]
|
||||||
Option value type:: binary data or Z85 text string
|
Option value type:: binary data or Z85 text string
|
||||||
@@ -98,7 +100,9 @@ ZMQ_CURVE_SERVERKEY: Retrieve current CURVE server key
|
|||||||
|
|
||||||
Retrieves the current server key for the client socket. You can
|
Retrieves the current server key for the client socket. You can
|
||||||
provide either a 32 byte buffer, to retrieve the binary key value, or
|
provide either a 32 byte buffer, to retrieve the binary key value, or
|
||||||
a 40 byte buffer, to retrieve the key in a printable Z85 format.
|
a 41-byte buffer, to retrieve the key in a printable Z85 format.
|
||||||
|
NOTE: to fetch a printable key, the buffer must be 41 bytes large
|
||||||
|
to hold the 40-char key value and one null byte.
|
||||||
|
|
||||||
[horizontal]
|
[horizontal]
|
||||||
Option value type:: binary data or Z85 text string
|
Option value type:: binary data or Z85 text string
|
||||||
|
|||||||
@@ -112,13 +112,17 @@ ZMQ_CURVE_PUBLICKEY: Set CURVE public key
|
|||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
Sets the socket's long term public key. You must set this on CURVE client
|
Sets the socket's long term public key. You must set this on CURVE client
|
||||||
sockets, see linkzmq:zmq_curve[7]. You can provide the key as 32 binary
|
sockets, see linkzmq:zmq_curve[7]. You can provide the key as 32 binary
|
||||||
bytes, or as a 40-character string encoded in the Z85 encoding format.
|
bytes, or as a 40-character string encoded in the Z85 encoding format and
|
||||||
The public key must always be used with the matching secret key. To
|
terminated in a null byte. The public key must always be used with the
|
||||||
generate a public/secret key pair, use linkzmq:zmq_curve_keypair[3].
|
matching secret key. To generate a public/secret key pair, use
|
||||||
|
linkzmq:zmq_curve_keypair[3].
|
||||||
|
|
||||||
|
NOTE: an option value size of 40 is supported for backwards compatibility,
|
||||||
|
though is deprecated.
|
||||||
|
|
||||||
[horizontal]
|
[horizontal]
|
||||||
Option value type:: binary data or Z85 text string
|
Option value type:: binary data or Z85 text string
|
||||||
Option value size:: 32 or 40
|
Option value size:: 32 or 41
|
||||||
Default value:: NULL
|
Default value:: NULL
|
||||||
Applicable socket types:: all, when using TCP transport
|
Applicable socket types:: all, when using TCP transport
|
||||||
|
|
||||||
@@ -128,12 +132,15 @@ ZMQ_CURVE_SECRETKEY: Set CURVE secret key
|
|||||||
Sets the socket's long term secret key. You must set this on both CURVE
|
Sets the socket's long term secret key. You must set this on both CURVE
|
||||||
client and server sockets, see linkzmq:zmq_curve[7]. You can provide the
|
client and server sockets, see linkzmq:zmq_curve[7]. You can provide the
|
||||||
key as 32 binary bytes, or as a 40-character string encoded in the Z85
|
key as 32 binary bytes, or as a 40-character string encoded in the Z85
|
||||||
encoding format. To generate a public/secret key pair, use
|
encoding format and terminated in a null byte. To generate a public/secret
|
||||||
linkzmq:zmq_curve_keypair[3].
|
key pair, use linkzmq:zmq_curve_keypair[3].
|
||||||
|
|
||||||
|
NOTE: an option value size of 40 is supported for backwards compatibility,
|
||||||
|
though is deprecated.
|
||||||
|
|
||||||
[horizontal]
|
[horizontal]
|
||||||
Option value type:: binary data or Z85 text string
|
Option value type:: binary data or Z85 text string
|
||||||
Option value size:: 32 or 40
|
Option value size:: 32 or 41
|
||||||
Default value:: NULL
|
Default value:: NULL
|
||||||
Applicable socket types:: all, when using TCP transport
|
Applicable socket types:: all, when using TCP transport
|
||||||
|
|
||||||
@@ -160,12 +167,17 @@ ZMQ_CURVE_SERVERKEY: Set CURVE server key
|
|||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
Sets the socket's long term server key. You must set this on CURVE client
|
Sets the socket's long term server key. You must set this on CURVE client
|
||||||
sockets, see linkzmq:zmq_curve[7]. You can provide the key as 32 binary
|
sockets, see linkzmq:zmq_curve[7]. You can provide the key as 32 binary
|
||||||
bytes, or as a 40-character string encoded in the Z85 encoding format.
|
bytes, or as a 40-character string encoded in the Z85 encoding format and
|
||||||
This key must have been generated together with the server's secret key.
|
terminated in a null byte. This key must have been generated together with
|
||||||
|
the server's secret key. To generate a public/secret key pair, use
|
||||||
|
linkzmq:zmq_curve_keypair[3].
|
||||||
|
|
||||||
|
NOTE: an option value size of 40 is supported for backwards compatibility,
|
||||||
|
though is deprecated.
|
||||||
|
|
||||||
[horizontal]
|
[horizontal]
|
||||||
Option value type:: binary data or Z85 text string
|
Option value type:: binary data or Z85 text string
|
||||||
Option value size:: 32 or 40
|
Option value size:: 32 or 41
|
||||||
Default value:: NULL
|
Default value:: NULL
|
||||||
Applicable socket types:: all, when using TCP transport
|
Applicable socket types:: all, when using TCP transport
|
||||||
|
|
||||||
|
|||||||
@@ -366,17 +366,30 @@ int zmq::options_t::setsockopt (int option_, const void *optval_,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ZMQ_CURVE_PUBLICKEY:
|
case ZMQ_CURVE_PUBLICKEY:
|
||||||
|
// TODO: refactor repeated code for these three options
|
||||||
|
// into set_curve_key (destination, optval, optlen) method
|
||||||
|
// ==> set_curve_key (curve_public_key, optval_, optvallen_);
|
||||||
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;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (optvallen_ == CURVE_KEYSIZE_Z85) {
|
if (optvallen_ == CURVE_KEYSIZE_Z85 + 1) {
|
||||||
zmq_z85_decode (curve_public_key, (char *) optval_);
|
zmq_z85_decode (curve_public_key, (char *) optval_);
|
||||||
mechanism = ZMQ_CURVE;
|
mechanism = ZMQ_CURVE;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
// Deprecated, not symmetrical with zmq_getsockopt
|
||||||
|
if (optvallen_ == CURVE_KEYSIZE_Z85) {
|
||||||
|
char z85_key [41];
|
||||||
|
memcpy (z85_key, (char *) optval_, CURVE_KEYSIZE_Z85);
|
||||||
|
z85_key [CURVE_KEYSIZE_Z85] = 0;
|
||||||
|
zmq_z85_decode (curve_public_key, z85_key);
|
||||||
|
mechanism = ZMQ_CURVE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZMQ_CURVE_SECRETKEY:
|
case ZMQ_CURVE_SECRETKEY:
|
||||||
@@ -386,25 +399,46 @@ int zmq::options_t::setsockopt (int option_, const void *optval_,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (optvallen_ == CURVE_KEYSIZE_Z85) {
|
if (optvallen_ == CURVE_KEYSIZE_Z85 + 1) {
|
||||||
zmq_z85_decode (curve_secret_key, (char *) optval_);
|
zmq_z85_decode (curve_secret_key, (char *) optval_);
|
||||||
mechanism = ZMQ_CURVE;
|
mechanism = ZMQ_CURVE;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
// Deprecated, not symmetrical with zmq_getsockopt
|
||||||
|
if (optvallen_ == CURVE_KEYSIZE_Z85) {
|
||||||
|
char z85_key [41];
|
||||||
|
memcpy (z85_key, (char *) optval_, CURVE_KEYSIZE_Z85);
|
||||||
|
z85_key [CURVE_KEYSIZE_Z85] = 0;
|
||||||
|
zmq_z85_decode (curve_secret_key, z85_key);
|
||||||
|
mechanism = ZMQ_CURVE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZMQ_CURVE_SERVERKEY:
|
case ZMQ_CURVE_SERVERKEY:
|
||||||
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;
|
|
||||||
mechanism = ZMQ_CURVE;
|
mechanism = ZMQ_CURVE;
|
||||||
|
as_server = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (optvallen_ == CURVE_KEYSIZE_Z85) {
|
if (optvallen_ == CURVE_KEYSIZE_Z85 + 1) {
|
||||||
zmq_z85_decode (curve_server_key, (char *) optval_);
|
zmq_z85_decode (curve_server_key, (char *) optval_);
|
||||||
as_server = 0;
|
|
||||||
mechanism = ZMQ_CURVE;
|
mechanism = ZMQ_CURVE;
|
||||||
|
as_server = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
// Deprecated, not symmetrical with zmq_getsockopt
|
||||||
|
if (optvallen_ == CURVE_KEYSIZE_Z85) {
|
||||||
|
char z85_key [41];
|
||||||
|
memcpy (z85_key, (char *) optval_, CURVE_KEYSIZE_Z85);
|
||||||
|
z85_key [CURVE_KEYSIZE_Z85] = 0;
|
||||||
|
zmq_z85_decode (curve_server_key, z85_key);
|
||||||
|
mechanism = ZMQ_CURVE;
|
||||||
|
as_server = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ int main (void)
|
|||||||
int as_server = 1;
|
int as_server = 1;
|
||||||
rc = zmq_setsockopt (server, ZMQ_CURVE_SERVER, &as_server, sizeof (int));
|
rc = zmq_setsockopt (server, ZMQ_CURVE_SERVER, &as_server, sizeof (int));
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
rc = zmq_setsockopt (server, ZMQ_CURVE_SECRETKEY, server_secret, 40);
|
rc = zmq_setsockopt (server, ZMQ_CURVE_SECRETKEY, server_secret, 41);
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
rc = zmq_setsockopt (server, ZMQ_IDENTITY, "IDENT", 6);
|
rc = zmq_setsockopt (server, ZMQ_IDENTITY, "IDENT", 6);
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
@@ -121,11 +121,11 @@ int main (void)
|
|||||||
// Check CURVE security with valid credentials
|
// Check CURVE security with valid credentials
|
||||||
void *client = zmq_socket (ctx, ZMQ_DEALER);
|
void *client = zmq_socket (ctx, ZMQ_DEALER);
|
||||||
assert (client);
|
assert (client);
|
||||||
rc = zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, server_public, 40);
|
rc = zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, server_public, 41);
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
rc = zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, client_public, 40);
|
rc = zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, client_public, 41);
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
rc = zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, client_secret, 40);
|
rc = zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, client_secret, 41);
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
rc = zmq_connect (client, "tcp://localhost:9998");
|
rc = zmq_connect (client, "tcp://localhost:9998");
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
@@ -138,11 +138,11 @@ int main (void)
|
|||||||
char garbage_key [] = "0000111122223333444455556666777788889999";
|
char garbage_key [] = "0000111122223333444455556666777788889999";
|
||||||
client = zmq_socket (ctx, ZMQ_DEALER);
|
client = zmq_socket (ctx, ZMQ_DEALER);
|
||||||
assert (client);
|
assert (client);
|
||||||
rc = zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, garbage_key, 40);
|
rc = zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, garbage_key, 41);
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
rc = zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, client_public, 40);
|
rc = zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, client_public, 41);
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
rc = zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, client_secret, 40);
|
rc = zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, client_secret, 41);
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
rc = zmq_connect (client, "tcp://localhost:9998");
|
rc = zmq_connect (client, "tcp://localhost:9998");
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
@@ -153,11 +153,11 @@ int main (void)
|
|||||||
// This will be caught by the curve_server class, not passed to ZAP
|
// This will be caught by the curve_server class, not passed to ZAP
|
||||||
client = zmq_socket (ctx, ZMQ_DEALER);
|
client = zmq_socket (ctx, ZMQ_DEALER);
|
||||||
assert (client);
|
assert (client);
|
||||||
rc = zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, server_public, 40);
|
rc = zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, server_public, 41);
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
rc = zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, garbage_key, 40);
|
rc = zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, garbage_key, 41);
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
rc = zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, client_secret, 40);
|
rc = zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, client_secret, 41);
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
rc = zmq_connect (client, "tcp://localhost:9998");
|
rc = zmq_connect (client, "tcp://localhost:9998");
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
@@ -168,11 +168,11 @@ int main (void)
|
|||||||
// This will be caught by the curve_server class, not passed to ZAP
|
// This will be caught by the curve_server class, not passed to ZAP
|
||||||
client = zmq_socket (ctx, ZMQ_DEALER);
|
client = zmq_socket (ctx, ZMQ_DEALER);
|
||||||
assert (client);
|
assert (client);
|
||||||
rc = zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, server_public, 40);
|
rc = zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, server_public, 41);
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
rc = zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, client_public, 40);
|
rc = zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, client_public, 41);
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
rc = zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, garbage_key, 40);
|
rc = zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, garbage_key, 41);
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
rc = zmq_connect (client, "tcp://localhost:9998");
|
rc = zmq_connect (client, "tcp://localhost:9998");
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
@@ -187,11 +187,11 @@ int main (void)
|
|||||||
|
|
||||||
client = zmq_socket (ctx, ZMQ_DEALER);
|
client = zmq_socket (ctx, ZMQ_DEALER);
|
||||||
assert (client);
|
assert (client);
|
||||||
rc = zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, server_public, 40);
|
rc = zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, server_public, 41);
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
rc = zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, bogus_public, 40);
|
rc = zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, bogus_public, 41);
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
rc = zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, bogus_secret, 40);
|
rc = zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, bogus_secret, 41);
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
rc = zmq_connect (client, "tcp://localhost:9998");
|
rc = zmq_connect (client, "tcp://localhost:9998");
|
||||||
assert (rc == 0);
|
assert (rc == 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user