zcert_t * zcert_new_from (byte *public_key, byte *secret_key) { zcert_t *self = (zcert_t *) zmalloc (sizeof (zcert_t)); if (!self) return NULL; assert (public_key); assert (secret_key); self->metadata = zhash_new (); if (self->metadata) { zhash_autofree (self->metadata); memcpy (self->public_key, public_key, 32); memcpy (self->secret_key, secret_key, 32); #if (ZMQ_VERSION_MAJOR == 4) zmq_z85_encode (self->public_txt, self->public_key, 32); zmq_z85_encode (self->secret_txt, self->secret_key, 32); #else strcpy (self->public_txt, FORTY_ZEROES); strcpy (self->secret_txt, FORTY_ZEROES); #endif } else zcert_destroy (&self); return self; }
int main (void) { #ifdef HAVE_LIBSODIUM # if crypto_box_PUBLICKEYBYTES != 32 \ || crypto_box_SECRETKEYBYTES != 32 # error "libsodium not built correctly" # endif puts ("This tool generates a CurveZMQ keypair, as two printable strings you can"); puts ("use in configuration files or source code. The encoding uses Z85, which"); puts ("is a base-85 format that is described in 0MQ RFC 32, and which has an"); puts ("implementation in the z85_codec.h source used by this tool. The keypair"); puts ("always works with the secret key held by one party and the public key"); puts ("distributed (securely!) to peers wishing to connect to it."); uint8_t public_key [32]; uint8_t secret_key [32]; int rc = crypto_box_keypair (public_key, secret_key); assert (rc == 0); char encoded [41]; zmq_z85_encode (encoded, public_key, 32); puts ("\n== CURVE PUBLIC KEY =="); puts (encoded); zmq_z85_encode (encoded, secret_key, 32); puts ("\n== CURVE SECRET KEY =="); puts (encoded); #else puts ("To build curve_keygen, please install libsodium and then rebuild libzmq."); #endif exit (0); }
int zmq_curve_keypair (char *z85_public_key_, char *z85_secret_key_) { #if defined(ZMQ_HAVE_CURVE) #if crypto_box_PUBLICKEYBYTES != 32 || crypto_box_SECRETKEYBYTES != 32 #error "CURVE encryption library not built correctly" #endif uint8_t public_key[32]; uint8_t secret_key[32]; zmq::random_open (); int res = crypto_box_keypair (public_key, secret_key); zmq_z85_encode (z85_public_key_, public_key, 32); zmq_z85_encode (z85_secret_key_, secret_key, 32); zmq::random_close (); return res; #else (void) z85_public_key_, (void) z85_secret_key_; errno = ENOTSUP; return -1; #endif }
int zmq_curve_keypair (char *z85_public_key, char *z85_secret_key) { #ifdef HAVE_LIBSODIUM # if crypto_box_PUBLICKEYBYTES != 32 \ || crypto_box_SECRETKEYBYTES != 32 # error "libsodium not built correctly" # endif uint8_t public_key [32]; uint8_t secret_key [32]; int rc = crypto_box_keypair (public_key, secret_key); // Is there a sensible errno to set here? if (rc) return rc; zmq_z85_encode (z85_public_key, public_key, 32); zmq_z85_encode (z85_secret_key, secret_key, 32); return 0; #else // requires libsodium errno = ENOTSUP; return -1; #endif }
int zmq_curve_keypair (char *z85_public_key, char *z85_secret_key) { #if defined (ZMQ_HAVE_CURVE) # if crypto_box_PUBLICKEYBYTES != 32 \ || crypto_box_SECRETKEYBYTES != 32 # error "CURVE encryption library not built correctly" # endif uint8_t public_key [32]; uint8_t secret_key [32]; int rc = crypto_box_keypair (public_key, secret_key); // Is there a sensible errno to set here? if (rc) return rc; zmq_z85_encode (z85_public_key, public_key, 32); zmq_z85_encode (z85_secret_key, secret_key, 32); return 0; #else (void) z85_public_key, (void) z85_secret_key; errno = ENOTSUP; return -1; #endif }
int zmq_curve_public (char *z85_public_key, const char *z85_secret_key) { #if defined (ZMQ_HAVE_CURVE) # if crypto_box_PUBLICKEYBYTES != 32 \ || crypto_box_SECRETKEYBYTES != 32 # error "CURVE encryption library not built correctly" # endif uint8_t public_key[32]; uint8_t secret_key[32]; if (zmq_z85_decode (secret_key, z85_secret_key) == NULL) return -1; // Return codes are suppressed as none of these can actually fail. crypto_scalarmult_base (public_key, secret_key); zmq_z85_encode (z85_public_key, public_key, 32); return 0; #else (void) z85_public_key, (void) z85_secret_key; errno = ENOTSUP; return -1; #endif }
static zap_request_t * s_zap_request_new (zsock_t *handler, bool verbose) { zap_request_t *self = (zap_request_t *) zmalloc (sizeof (zap_request_t)); if (!self) return NULL; // Store handler socket so we can send a reply easily self->handler = handler; self->verbose = verbose; zmsg_t *request = zmsg_recv (handler); if (!request) { // interrupted s_zap_request_destroy (&self); return NULL; } // Get all standard frames off the handler socket self->version = zmsg_popstr (request); self->sequence = zmsg_popstr (request); self->domain = zmsg_popstr (request); self->address = zmsg_popstr (request); self->identity = zmsg_popstr (request); self->mechanism = zmsg_popstr (request); // If the version is wrong, we're linked with a bogus libzmq, so die assert (streq (self->version, "1.0")); // Get mechanism-specific frames if (streq (self->mechanism, "PLAIN")) { self->username = zmsg_popstr (request); self->password = zmsg_popstr (request); } else if (streq (self->mechanism, "CURVE")) { zframe_t *frame = zmsg_pop (request); assert (zframe_size (frame) == 32); self->client_key = (char *) zmalloc (41); #if (ZMQ_VERSION_MAJOR == 4) zmq_z85_encode (self->client_key, zframe_data (frame), 32); #endif zframe_destroy (&frame); } else if (streq (self->mechanism, "GSSAPI")) self->principal = zmsg_popstr (request); if (self->verbose) zsys_info ("zauth: ZAP request mechanism=%s ipaddress=%s", self->mechanism, self->address); zmsg_destroy (&request); return self; }
zcert_t * zcert_new_from (byte *public_key, byte *secret_key) { zcert_t *self = (zcert_t *) zmalloc (sizeof (zcert_t)); assert (self); assert (public_key); assert (secret_key); self->metadata = zhash_new (); zhash_autofree (self->metadata); memcpy (self->public_key, public_key, 32); memcpy (self->secret_key, secret_key, 32); #if (ZMQ_VERSION_MAJOR == 4) zmq_z85_encode (self->public_txt, self->public_key, 32); zmq_z85_encode (self->secret_txt, self->secret_key, 32); #else strcpy (self->public_txt, "0000000000000000000000000000000000000000"); strcpy (self->secret_txt, "0000000000000000000000000000000000000000"); #endif return self; }
void test__zmq_z85_encode__zmq_z85_decode__roundtrip ( const uint8_t (&test_data_)[SIZE]) { char test_data_z85[SIZE * 5 / 4 + 1]; char *res1 = zmq_z85_encode (test_data_z85, test_data_, SIZE); assert (res1 != NULL); uint8_t test_data_decoded[SIZE]; uint8_t *res2 = zmq_z85_decode (test_data_decoded, test_data_z85); assert (res2 != NULL); int res3 = memcmp (test_data_, test_data_decoded, SIZE); assert (res3 == 0); }
// Test vector: rfc.zeromq.org/spec:32/Z85 void test__zmq_z85_encode__valid__success () { static const size_t size = 8; static const size_t length = size * 5 / 4; static const uint8_t decoded[size] = {0x86, 0x4F, 0xD2, 0x6F, 0xB5, 0x59, 0xF7, 0x5B}; static const char expected[length + 1] = "HelloWorld"; char out_encoded[length + 1] = {0}; errno = 0; assert (zmq_z85_encode (out_encoded, decoded, size) != NULL); assert (streq (out_encoded, expected)); assert (zmq_errno () == 0); }
static void zap_handler (void *handler) { // Process ZAP requests forever while (true) { char *version = s_recv (handler); if (!version) break; // Terminating char *sequence = s_recv (handler); char *domain = s_recv (handler); char *address = s_recv (handler); char *identity = s_recv (handler); char *mechanism = s_recv (handler); uint8_t client_key [32]; int size = zmq_recv (handler, client_key, 32, 0); assert (size == 32); char client_key_text [40]; zmq_z85_encode (client_key_text, client_key, 32); assert (streq (version, "1.0")); assert (streq (mechanism, "CURVE")); assert (streq (identity, "IDENT")); s_sendmore (handler, version); s_sendmore (handler, sequence); if (streq (client_key_text, client_public)) { s_sendmore (handler, "200"); s_sendmore (handler, "OK"); s_sendmore (handler, "anonymous"); s_send (handler, ""); } else { s_sendmore (handler, "400"); s_sendmore (handler, "Invalid client public key"); s_sendmore (handler, ""); s_send (handler, ""); } free (version); free (sequence); free (domain); free (address); free (identity); free (mechanism); } zmq_close (handler); }
void test__zmq_z85_decode__zmq_z85_encode__roundtrip ( const char (&test_data_)[SIZE]) { const size_t decoded_size = (SIZE - 1) * 4 / 5; uint8_t test_data_decoded[decoded_size]; uint8_t *res1 = zmq_z85_decode (test_data_decoded, test_data_); assert (res1 != NULL); char test_data_z85[SIZE]; char *res2 = zmq_z85_encode (test_data_z85, test_data_decoded, decoded_size); assert (res2 != NULL); int res3 = memcmp (test_data_, test_data_z85, SIZE); assert (res3 == 0); }
static zap_request_t * zap_request_new (void *handler) { #if (ZMQ_VERSION_MAJOR == 4) zap_request_t *self = (zap_request_t *) zmalloc (sizeof (zap_request_t)); assert (self); // Store handler socket so we can send a reply easily self->handler = handler; zmsg_t *request = zmsg_recv (handler); // Get all standard frames off the handler socket self->version = zmsg_popstr (request); self->sequence = zmsg_popstr (request); self->domain = zmsg_popstr (request); self->address = zmsg_popstr (request); self->identity = zmsg_popstr (request); self->mechanism = zmsg_popstr (request); // If the version is wrong, we're linked with a bogus libzmq, so die assert (streq (self->version, "1.0")); // Get mechanism-specific frames if (streq (self->mechanism, "PLAIN")) { self->username = zmsg_popstr (request); self->password = zmsg_popstr (request); } else if (streq (self->mechanism, "CURVE")) { zframe_t *frame = zmsg_pop (request); assert (zframe_size (frame) == 32); self->client_key = (char *) zmalloc (41); zmq_z85_encode (self->client_key, zframe_data (frame), 32); zframe_destroy (&frame); } else if (streq (self->mechanism, "GSSAPI")) self->principal = zmsg_popstr (request); zmsg_destroy (&request); return self; #else return NULL; #endif }
JNIEXPORT jstring JNICALL Java_org_zeromq_ZMQ_00024Curve_z85Encode(JNIEnv *env, jclass cls, jbyteArray key) { #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4,0,0) jbyte *in_key = env->GetByteArrayElements (key, NULL); assert (in_key); char string_key [41]; if (NULL == zmq_z85_encode (string_key, reinterpret_cast<uint8_t*>(in_key), 32)) { env->ReleaseByteArrayElements (key, in_key, 0); return NULL; } env->ReleaseByteArrayElements (key, in_key, 0); jstring result = env->NewStringUTF (string_key); assert (result); return result; #else raise_exception (env, ENOTSUP); return NULL; #endif }
int zmq::options_t::getsockopt (int option_, void *optval_, size_t *optvallen_) { bool is_int = (*optvallen_ == sizeof (int)); int *value = (int *) optval_; #if defined (ZMQ_ACT_MILITANT) bool malformed = true; // Did caller pass a bad option value? #endif switch (option_) { case ZMQ_SNDHWM: if (is_int) { *value = sndhwm; return 0; } break; case ZMQ_RCVHWM: if (is_int) { *value = rcvhwm; return 0; } break; case ZMQ_AFFINITY: if (*optvallen_ == sizeof (uint64_t)) { *((uint64_t *) optval_) = affinity; return 0; } break; case ZMQ_IDENTITY: if (*optvallen_ >= identity_size) { memcpy (optval_, identity, identity_size); *optvallen_ = identity_size; return 0; } break; case ZMQ_RATE: if (is_int) { *value = rate; return 0; } break; case ZMQ_RECOVERY_IVL: if (is_int) { *value = recovery_ivl; return 0; } break; case ZMQ_SNDBUF: if (is_int) { *value = sndbuf; return 0; } break; case ZMQ_RCVBUF: if (is_int) { *value = rcvbuf; return 0; } break; case ZMQ_TOS: if (is_int) { *value = tos; return 0; } break; case ZMQ_TYPE: if (is_int) { *value = type; return 0; } break; case ZMQ_LINGER: if (is_int) { *value = linger; return 0; } break; case ZMQ_RECONNECT_IVL: if (is_int) { *value = reconnect_ivl; return 0; } break; case ZMQ_RECONNECT_IVL_MAX: if (is_int) { *value = reconnect_ivl_max; return 0; } break; case ZMQ_BACKLOG: if (is_int) { *value = backlog; return 0; } break; case ZMQ_MAXMSGSIZE: if (*optvallen_ == sizeof (int64_t)) { *((int64_t *) optval_) = maxmsgsize; *optvallen_ = sizeof (int64_t); return 0; } break; case ZMQ_MULTICAST_HOPS: if (is_int) { *value = multicast_hops; return 0; } break; case ZMQ_RCVTIMEO: if (is_int) { *value = rcvtimeo; return 0; } break; case ZMQ_SNDTIMEO: if (is_int) { *value = sndtimeo; return 0; } break; case ZMQ_IPV4ONLY: if (is_int) { *value = 1 - ipv6; return 0; } break; case ZMQ_IPV6: if (is_int) { *value = ipv6; return 0; } break; case ZMQ_IMMEDIATE: if (is_int) { *value = immediate; return 0; } break; case ZMQ_SOCKS_PROXY: if (*optvallen_ >= socks_proxy_address.size () + 1) { memcpy (optval_, socks_proxy_address.c_str (), socks_proxy_address.size () + 1); *optvallen_ = socks_proxy_address.size () + 1; return 0; } break; case ZMQ_TCP_KEEPALIVE: if (is_int) { *value = tcp_keepalive; return 0; } break; case ZMQ_TCP_KEEPALIVE_CNT: if (is_int) { *value = tcp_keepalive_cnt; return 0; } break; case ZMQ_TCP_KEEPALIVE_IDLE: if (is_int) { *value = tcp_keepalive_idle; return 0; } break; case ZMQ_TCP_KEEPALIVE_INTVL: if (is_int) { *value = tcp_keepalive_intvl; return 0; } break; case ZMQ_MECHANISM: if (is_int) { *value = mechanism; return 0; } break; case ZMQ_PLAIN_SERVER: if (is_int) { *value = as_server && mechanism == ZMQ_PLAIN; return 0; } break; case ZMQ_PLAIN_USERNAME: if (*optvallen_ >= plain_username.size () + 1) { memcpy (optval_, plain_username.c_str (), plain_username.size () + 1); *optvallen_ = plain_username.size () + 1; return 0; } break; case ZMQ_PLAIN_PASSWORD: if (*optvallen_ >= plain_password.size () + 1) { memcpy (optval_, plain_password.c_str (), plain_password.size () + 1); *optvallen_ = plain_password.size () + 1; return 0; } break; case ZMQ_ZAP_DOMAIN: if (*optvallen_ >= zap_domain.size () + 1) { memcpy (optval_, zap_domain.c_str (), zap_domain.size () + 1); *optvallen_ = zap_domain.size () + 1; return 0; } break; // If libsodium isn't installed, these options provoke EINVAL # ifdef HAVE_LIBSODIUM case ZMQ_CURVE_SERVER: if (is_int) { *value = as_server && mechanism == ZMQ_CURVE; return 0; } break; case ZMQ_CURVE_PUBLICKEY: if (*optvallen_ == CURVE_KEYSIZE) { memcpy (optval_, curve_public_key, CURVE_KEYSIZE); return 0; } else if (*optvallen_ == CURVE_KEYSIZE_Z85 + 1) { zmq_z85_encode ((char *) optval_, curve_public_key, CURVE_KEYSIZE); return 0; } break; case ZMQ_CURVE_SECRETKEY: if (*optvallen_ == CURVE_KEYSIZE) { memcpy (optval_, curve_secret_key, CURVE_KEYSIZE); return 0; } else if (*optvallen_ == CURVE_KEYSIZE_Z85 + 1) { zmq_z85_encode ((char *) optval_, curve_secret_key, CURVE_KEYSIZE); return 0; } break; case ZMQ_CURVE_SERVERKEY: if (*optvallen_ == CURVE_KEYSIZE) { memcpy (optval_, curve_server_key, CURVE_KEYSIZE); return 0; } else if (*optvallen_ == CURVE_KEYSIZE_Z85 + 1) { zmq_z85_encode ((char *) optval_, curve_server_key, CURVE_KEYSIZE); return 0; } break; # endif case ZMQ_CONFLATE: if (is_int) { *value = conflate; return 0; } break; // If libgssapi isn't installed, these options provoke EINVAL # ifdef HAVE_LIBGSSAPI_KRB5 case ZMQ_GSSAPI_SERVER: if (is_int) { *value = as_server && mechanism == ZMQ_GSSAPI; return 0; } break; case ZMQ_GSSAPI_PRINCIPAL: if (*optvallen_ >= gss_principal.size () + 1) { memcpy (optval_, gss_principal.c_str (), gss_principal.size () + 1); *optvallen_ = gss_principal.size () + 1; return 0; } break; case ZMQ_GSSAPI_SERVICE_PRINCIPAL: if (*optvallen_ >= gss_service_principal.size () + 1) { memcpy (optval_, gss_service_principal.c_str (), gss_service_principal.size () + 1); *optvallen_ = gss_service_principal.size () + 1; return 0; } break; case ZMQ_GSSAPI_PLAINTEXT: if (is_int) { *value = gss_plaintext; return 0; } break; #endif case ZMQ_HANDSHAKE_IVL: if (is_int) { *value = handshake_ivl; return 0; } break; default: #if defined (ZMQ_ACT_MILITANT) malformed = false; #endif break; } #if defined (ZMQ_ACT_MILITANT) if (malformed) zmq_assert (false); #endif errno = EINVAL; return -1; }
// Buffer length must be evenly divisible by 4 or must fail with EINVAL. void test__zmq_z85_encode__invalid__failure (size_t size_) { errno = 0; assert (zmq_z85_encode (NULL, NULL, size_) == NULL); assert (zmq_errno () == EINVAL); }
int zmq::options_t::getsockopt (int option_, void *optval_, size_t *optvallen_) { bool is_int = (*optvallen_ == sizeof (int)); int *value = (int *) optval_; switch (option_) { case ZMQ_SNDHWM: if (is_int) { *value = sndhwm; return 0; } break; case ZMQ_RCVHWM: if (is_int) { *value = rcvhwm; return 0; } break; case ZMQ_AFFINITY: if (*optvallen_ == sizeof (uint64_t)) { *((uint64_t *) optval_) = affinity; return 0; } break; case ZMQ_IDENTITY: if (*optvallen_ >= identity_size) { memcpy (optval_, identity, identity_size); *optvallen_ = identity_size; return 0; } break; case ZMQ_RATE: if (is_int) { *value = rate; return 0; } break; case ZMQ_RECOVERY_IVL: if (is_int) { *value = recovery_ivl; return 0; } break; case ZMQ_SNDBUF: if (is_int) { *value = sndbuf; return 0; } break; case ZMQ_RCVBUF: if (is_int) { *value = rcvbuf; return 0; } break; case ZMQ_TOS: if (is_int) { *value = tos; return 0; } break; case ZMQ_TYPE: if (is_int) { *value = type; return 0; } break; case ZMQ_LINGER: if (is_int) { *value = linger; return 0; } break; case ZMQ_RECONNECT_IVL: if (is_int) { *value = reconnect_ivl; return 0; } break; case ZMQ_RECONNECT_IVL_MAX: if (is_int) { *value = reconnect_ivl_max; return 0; } break; case ZMQ_BACKLOG: if (is_int) { *value = backlog; return 0; } break; case ZMQ_MAXMSGSIZE: if (*optvallen_ == sizeof (int64_t)) { *((int64_t *) optval_) = maxmsgsize; *optvallen_ = sizeof (int64_t); return 0; } break; case ZMQ_MULTICAST_HOPS: if (is_int) { *value = multicast_hops; return 0; } break; case ZMQ_RCVTIMEO: if (is_int) { *value = rcvtimeo; return 0; } break; case ZMQ_SNDTIMEO: if (is_int) { *value = sndtimeo; return 0; } break; case ZMQ_IPV4ONLY: if (is_int) { *value = 1 - ipv6; return 0; } break; case ZMQ_IPV6: if (is_int) { *value = ipv6; return 0; } break; case ZMQ_IMMEDIATE: if (is_int) { *value = immediate; return 0; } break; case ZMQ_TCP_KEEPALIVE: if (is_int) { *value = tcp_keepalive; return 0; } break; case ZMQ_TCP_KEEPALIVE_CNT: if (is_int) { *value = tcp_keepalive_cnt; return 0; } break; case ZMQ_TCP_KEEPALIVE_IDLE: if (is_int) { *value = tcp_keepalive_idle; return 0; } break; case ZMQ_TCP_KEEPALIVE_INTVL: if (is_int) { *value = tcp_keepalive_intvl; return 0; } break; # if defined ZMQ_HAVE_SO_PEERCRED || defined ZMQ_HAVE_LOCAL_PEERCRED case ZMQ_ZAP_IPC_CREDS: if (is_int) { *value = zap_ipc_creds; return 0; } break; # endif case ZMQ_MECHANISM: if (is_int) { *value = mechanism; return 0; } break; case ZMQ_PLAIN_SERVER: if (is_int) { *value = as_server && mechanism == ZMQ_PLAIN; return 0; } break; case ZMQ_PLAIN_USERNAME: if (*optvallen_ >= plain_username.size () + 1) { memcpy (optval_, plain_username.c_str (), plain_username.size () + 1); *optvallen_ = plain_username.size () + 1; return 0; } break; case ZMQ_PLAIN_PASSWORD: if (*optvallen_ >= plain_password.size () + 1) { memcpy (optval_, plain_password.c_str (), plain_password.size () + 1); *optvallen_ = plain_password.size () + 1; return 0; } break; case ZMQ_ZAP_DOMAIN: if (*optvallen_ >= zap_domain.size () + 1) { memcpy (optval_, zap_domain.c_str (), zap_domain.size () + 1); *optvallen_ = zap_domain.size () + 1; return 0; } break; // If libsodium isn't installed, these options provoke EINVAL # ifdef HAVE_LIBSODIUM case ZMQ_CURVE_SERVER: if (is_int) { *value = as_server && mechanism == ZMQ_CURVE; return 0; } break; case ZMQ_CURVE_PUBLICKEY: if (*optvallen_ == CURVE_KEYSIZE) { memcpy (optval_, curve_public_key, CURVE_KEYSIZE); return 0; } else if (*optvallen_ == CURVE_KEYSIZE_Z85 + 1) { zmq_z85_encode ((char *) optval_, curve_public_key, CURVE_KEYSIZE); return 0; } break; case ZMQ_CURVE_SECRETKEY: if (*optvallen_ == CURVE_KEYSIZE) { memcpy (optval_, curve_secret_key, CURVE_KEYSIZE); return 0; } else if (*optvallen_ == CURVE_KEYSIZE_Z85 + 1) { zmq_z85_encode ((char *) optval_, curve_secret_key, CURVE_KEYSIZE); return 0; } break; case ZMQ_CURVE_SERVERKEY: if (*optvallen_ == CURVE_KEYSIZE) { memcpy (optval_, curve_server_key, CURVE_KEYSIZE); return 0; } else if (*optvallen_ == CURVE_KEYSIZE_Z85 + 1) { zmq_z85_encode ((char *) optval_, curve_server_key, CURVE_KEYSIZE); return 0; } break; # endif case ZMQ_CONFLATE: if (is_int) { *value = conflate; return 0; } break; } errno = EINVAL; return -1; }
static std::string z85string(void *pv, size_t size) { std::vector<char> v; v.reserve(size * 1.25 + 1); zmq_z85_encode(v.data(), reinterpret_cast<uint8_t*>(pv), size); return std::string(v.data()); }