Code Monkey home page Code Monkey logo

czmq's People

Contributors

ahhentz avatar bluca avatar bluehaunter avatar brianknox avatar c-rack avatar claws avatar eclazi avatar evoskuil avatar hintjens avatar jemc avatar jimklimov avatar karolhrdina avatar lovmoen avatar methodmissing avatar mkoppanen avatar paddor avatar pijyoi avatar pmienk avatar ritchiecarroll avatar sappo avatar somdoron avatar sphaero avatar stephan57160 avatar taotetek avatar trevorbernard avatar twhittock avatar ulikoehler avatar vortechs2000 avatar vyskocilm avatar wesyoung avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

czmq's Issues

czmq_prelude.h confuses logging systems

czmq_prelude.h includes syslog.h, but it seems that nobody is using it. The problem is that this file defines macros like LOG_DEBUG, LOG_WARNING, etc.. and then confuses other logging systems that want to use the same names.

After deleting this include from czmq_prelude, czmq compile fines and the logging system does not complies. Any problem in removing this from czmq_prelude?

linger inconsistency

A socket default linger value is -1 (infinite) zmq_getsockopt, however when using czmq, the default is 0. It's a bit confusing. For example in the zguide lpclient.c setting the linger to 0 before closing the socket in case of error is crutial, and it's done under the hood.
While if somebody would like to code the syncpub.c example using czmq, without setting the linger probably won't work, because czmq sets the linger to 0.
what do you think?

zlist_head and zlist_next problem

Hi,

zlist_t *l = zlist_new();
char *s = "hi";
zlist_append(l,s);
printf("%s\n", (char*) zlist_head(l));
printf("%s\n", (char*) zlist_next(l));
printf("%s\n", (char*) zlist_head(l));
printf("%s\n", (char*) zlist_next(l));

and output is

hi
hi
hi
(null)

i would expect that last value of output would be "hi".

I understand that zlist_head is not doing anything with cursor. But maybe it could. Or we can have zlist_head_cursor() which would put cursor to the top

Ciao

Martin

"Possible Lost" blocks when using zloop under zthread

Summary: When utilizing a zloop from within a thread spawned by zthread valgrind claims that some blocks are possibly lost and some are still reachable. The problem only occurs if you start the zloop.

Details:
OS: Debian 6.0.7
Compiler: gcc (Debian 4.4.5-8) 4.4.5
Valgrind: valgrind-3.6.0.SVN-Debian

 CZMQ: 1.4.0
 ZMQ: 3.2.3

 Example: https://gist.github.com/JustonDavies/5265283

Notes: The example isn't exactly the most sensible thing but you should get the fundamental idea. Compile and run using the specified versions using Valgrind with --leak-check=full. If you comment Line 11 you will notice the problem can no longer be produced. Adding pollitems with zloop_poller appears to make the problem worse, but I haven't an example ready to prove it beyond reasonable doubt.

server / client example

would be great to have server / client example to get started ...or is there some code out there to look at?

zbeacon crash in s_get_interface

When I called zbeacon_new() I got a seg fault. I traced it to this line of zbeacon::s_get_interface()

if (interface->ifa_addr->sa_family == AF_INET)

I have two interfaces on my device where interface->ifa_addr is NULL. I fixed this with a check for NULL before using sa_family.

zbeacon: errors on SmartOS/Solaris

It appears the use of SIOCGIFADDR ioctl to get an interface broadcast address does not work on SmartOS/Solaris. They print error messages such as:

SmartOS:

E: (UDP) error 'No such device or address' on siocgifaddr
Assertion failed: false, file zbeacon.c, line 528, function s_handle_io_error

Solaris:

E: (UDP) error 'Error 0' on wlan0 not exist 
Assertion failed: false, file zbeacon.c, line 528, function s_handle_io_error

zmq.h from libzmq3.x requires <sys/uio.h>

Problem:

sys/uio.h is already included, but order of includes within czmq_prelude affects.

cc1: warnings being treated as errors
In file included from ../include/czmq_prelude.h:32,
                from zclock.c:45:
/home/jenkins/install/libzmq/gcc/include/zmq.h:342: error: ‘struct iovec’ declared inside parameter list
/home/jenkins/install/libzmq/gcc/include/zmq.h:342: error: its scope is only this definition or declaration, which is probably not what you want
/home/jenkins/install/libzmq/gcc/include/zmq.h:343: error: ‘struct iovec’ declared inside parameter list

Solution:

Reorder czmq_prelude.h

zsocket_close linger assertion fail

I might just be using it wrong, but this minimal testcase:

#include <czmq.h>
//Compile like this: g++ -o testclose close.cpp -lzmq -lczmq
int main() {
    zctx_t* ctx = zctx_new();
    void* sock = zsocket_new(ctx, ZMQ_PUSH);
    zsocket_destroy(ctx, &sock);
    zctx_destroy(&ctx);
}

yields the following error message on Ubuntu 13.04 x86_64 with ZeroMQ 3.2.2 and CZMQ 1.4.1 (both vanilla)

testclose: zsockopt.c:888: zsocket_set_linger: Assertion `rc == 0 || (*__errno_location ()) == (156384712 + 53)' failed.
zsh: abort (core dumped)  ./testclose

GDB shows the error occurs in zsocket_destroy. The socket type doesn't seem to make a difference.

I suppose a linger value < -1 is passed to zmq_setsockopt, but I didn't check that in detail.

Thanks in advance (I'm reporting this as issue instead of posting it at the mailing list because I suppose the code above is what the average user would write and expect to work)!

Suspicious `break;` in zloop_start (zloop.c:373)

This is not exactly a bug submission, as I haven't tested the code.

I'm porting zloop.c to another language, and the break; at zloop_start (zloop.c:373) is suspicious to me - it seems like it won't perform as desired.

Throughout zloop_start, the code sets rc's, and then uses break to exit the main loop and report the rc. However, this particular break is within a while loop within the outermost loop, and so it won't break out of the main loop as (I think) is desired. Instead, it will just break out of the inner loop.

Is this analysis valid?

doesn't compile on mingw32 due to redefinition of int32_t

ming32 (gcc 4.6.2) defines WIN32 and friends but provides stdint.h and sys/types.h which are included by process.h

workaround: check for "MINGW32" in czmq_prelude.h before typedef-ing size types.

if (defined(WINDOWS))

...

if !defined(MINGW32)

typedef __int32 int32_t;
typedef __int64 int64_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
typedef long ssize_t;

endif

...

endif

zmsg_recv_nowait

I am trying to create a priority queue that receives all messages from the zmq queue.

In that case, having a zloop informs you if there is a message or not, not the queue size. With a zmsg_recv_nowait , you can get all remaining messages, do some work and then return to the zloop.

I am new to this, so tell me if there is a better way of doing this.

Problem accessing secret key (doc issue?)

According to the current documentation, you access the secret key of a certificate this way:

CZMQ_EXPORT byte *  zcert_secret_key (zcert_t *self);

However, this function doesn't seem to exist:

  zcert_t *cert = zcert_new ();
  byte *secret = zcert_secret_key(cert);

When trying to compile this, gcc says:

undefined reference to `zcert_secret_key`

At least I could not find a definition of this function anywhere, just in the documentation and the includefile:

$ grep -r zcert_secret_key src/czmq-2.0.1/*
src/czmq-2.0.1/doc/zcert.3:    zcert_secret_key (zcert_t *self);
src/czmq-2.0.1/doc/zcert.txt:    zcert_secret_key (zcert_t *self);
src/czmq-2.0.1/include/zcert.h:    zcert_secret_key (zcert_t *self);

I digged through the source and realized, that there is a function zcert_secret in zcert.c:144 instead which returns a byte *, so I tried this one:

  zcert_t *cert = zcert_new ();
  byte *secret = zcert_secret(cert);

Now I get from gcc:

warning: initialization makes pointer from integer without a cast

Let's ignore the warning and use the result, i.e.:

  zcert_t *cert = zcert_new ();
  byte *secret = zcert_secret(cert);
  byte *public = zcert_public(cert);
  zcert_t *c = zcert_new_from(secret, public);

If I execute the resulting binary, I get:

$ gdb ./cert 
GNU gdb 6.1.1 [FreeBSD]
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "amd64-marcel-freebsd"...
(gdb) run
Starting program: cert 
[New LWP 100239]
[New Thread 802007400 (LWP 100239/cert)]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 802007400 (LWP 100239/cert)]
0x0000000801032816 in memcpy () from /lib/libc.so.7
(gdb) bt
#0  0x0000000801032816 in memcpy () from /lib/libc.so.7
#1  0x00000008008557ef in zcert_new_from (public_key=0x20180e0 <Error reading address 0x20180e0: Bad address>, 
    secret_key=0x20180c0 <Error reading address 0x20180c0: Bad address>) at zcert.c:99
#2  0x0000000000400a86 in main () at cert.c:33

So, this seems not to work either. Next, I tried to access the key just directly, just as it happens a lot at several places in zcert.c:

  zcert_t *cert = zcert_new ();
  byte *secret = cert->secret_key;

Now I get:

error: dereferencing pointer to incomplete type

Interestingly if I use an int for the return value of zcert_secret(), gcc doesn't complain anymore and there's some number in that value (e.g.: 33652928), but I was unable to use this number as input for zcert_new_from().

The same applies for the public key as well.

Finally, I figured a way out to get to the raw keys by using the z85 encoded versions and decoding them:

  zcert_t *cert = zcert_new ();
  uint8_t secret [32];
  uint8_t public [32];
  zmq_z85_decode(secret, zcert_secret_txt(cert));
  zmq_z85_decode(public, zcert_public_txt(cert));
  printf("1st:\ns: %s\np: %s\n", zcert_secret_txt(cert), zcert_public_txt(cert));
  zcert_t *c = zcert_new_from(public, secret);
  printf("\nRecreated:\ns: %s\np: %s\n", zcert_secret_txt(c), zcert_public_txt(c));

Compiles like a charm and prints out:

1st:
s: Gkk:]X+6t$Qj(C[z>}0s<6yJR17gN-bDj@zS2F#T
p: >O[snXF!/7d{?4hY0{(D}KuUD7hSB[aKEZGY@&zk

Recreated:
s: Gkk:]X+6t$Qj(C[z>}0s<6yJR17gN-bDj@zS2F#T
p: >O[snXF!/7d{?4hY0{(D}KuUD7hSB[aKEZGY@&zk

So, I can live with it, but it's not the way to do it according to the documentation.

Best regards,
Tom

MSVC 2012 Compile Errors

ztree.c fails to compile in MSVC 2012 for me. It seem to be valid c code that doesn't compile as c++.

2> ztree.c
2>C:\Czmq\src\ztree.c(68): error C2440: 'initializing' : cannot convert from 'void ' to 'ztree_t *'
2> Conversion from 'void
' to pointer to non-'void' requires an explicit cast
2>C:\Czmq\src\ztree.c(308): error C2440: 'initializing' : cannot convert from 'void ' to 'node_t *'
2> Conversion from 'void
' to pointer to non-'void' requires an explicit cast
2>C:\Czmq\src\ztree.c(344): error C2440: 'initializing' : cannot convert from 'void ' to 'node_t *'
2> Conversion from 'void
' to pointer to non-'void' requires an explicit cast
2>C:\Czmq\src\ztree.c(556): error C2440: 'initializing' : cannot convert from 'void ' to 'node_t *'
2> Conversion from 'void
' to pointer to non-'void' requires an explicit cast
2>C:\Czmq\src\ztree.c(615): error C2440: 'initializing' : cannot convert from 'void ' to 'zlist_t *'
2> Conversion from 'void
' to pointer to non-'void' requires an explicit cast
2>C:\Czmq\src\ztree.c(636): error C2440: 'initializing' : cannot convert from 'void ' to 'ztree_t *'
2> Conversion from 'void
' to pointer to non-'void' requires an explicit cast
2>C:\Czmq\src\ztree.c(667): error C2440: 'initializing' : cannot convert from 'void ' to 'FILE *'
2> Conversion from 'void
' to pointer to non-'void' requires an explicit cast
2>C:\Czmq\src\ztree.c(796): error C2664: 'strcmp' : cannot convert parameter 1 from 'void ' to 'const char *'
2> Conversion from 'void
' to pointer to non-'void' requires an explicit cast
2>C:\Czmq\src\ztree.c(815): error C2065: 'strcasecmp' : undeclared identifier
========== Rebuild All: 1 succeeded, 1 failed, 0 skipped ==========

build fails: ZMQ_ROUTER_MANDATORY undeclared

czmq version: git HEAD from today
zmq version: git from today (zmq_version reports: 3.2.1)

zsockopt.c: In function 'zsocket_set_router_mandatory':
zsockopt.c:981:38: error: 'ZMQ_ROUTER_MANDATORY' undeclared (first use in this function)
zsockopt.c:981:38: note: each undeclared identifier is reported only once for each function it appears in
make[2]: *** [zsockopt.lo] Fehler 1

kind regards

zloop timer event return code overwritten by poller

During the main zloop, the timer return code "rc" will be overwritten by poller return codes. See "rc" set at line 372 but is then overwritten at line 414.

This means it is possible for a timer's cancel (rc=-1) to be lost.

It's not the easiest code to test deterministically. I have written a small program that floods a poller and the timer is indeed ignored/written over. I can upload this if need be but the bug is easily identified reading the code: rc is not checked between a timer return and the poller return.

I've posted to zmq-dev but this might be the more logical place.

Thanks,
Sam

zlist_remove - does not set cursor appropriately?

I was inspecting the zlist code, and it looks like zlist_remove accidentally rewinds the cursor back one.

I think that zlist.c:267 should be:

self->cursor = prev->next;

instead of

self->cursor = prev;

Thoughts?

Suggested replacement for 'makecert' tool

In addition to issue #247 I'd suggest to replace the makecert key generation utility supplied with czmq. The version I wrote has the following features:

  • supply filename for the key via commandline
  • supply meta data via commandline
  • export public key from secret key
  • secret key encryption using AES256

For aes encryption I used libcrypto of openssl, since I was unable to figure out, how to use the aes functions in libsodium (there is some aes stuff in there but completely undocumented). Something like the function zcert_decrypt_secret() could be used in programs using encrypted secret keys.

I mark an encrypted secret key with an additional meta tag "aes256-encrypted-secret" which will be set to enabled, if encrypted. When using such a key in a program, one has to ask the user for the passphrase, load the secret key file using zcert_load(), look for that tag and if it's set, decrypt the secret key and create a new zcert_t from the decrypted secret key and the public key.

Code:

/*
    curve-genkey

    Certificate generator for ZeroMQ CURVE security. Produces two files:

    * id_curve25519        - public certificate
    * id_curve25519.secret - secret certificate

    Copyright (C) 2013 iMatix Corporation 
    Copyright (c) 2013 T.Linden

    Licensed under MIT/X11.

    Permission is hereby granted, free of charge, to any person obtaining 
    a copy of this software and associated documentation files (the 
    "Software"), to deal in the Software without restriction, including 
    without limitation the rights to use, copy, modify, merge, publish, 
    distribute, sublicense, and/or sell copies of the Software, and to 
    permit persons to whom the Software is furnished to do so, subject to
    the following conditions:

    The above copyright notice and this permission notice shall be 
    included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#define _BSD_SOURCE

#include <czmq.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <termios.h>
#include <openssl/evp.h>

/**
  AES functions is public domain code. 
  from http://saju.net.in/code/misc/openssl_aes.c.txt
  Saju Pillai ([email protected])
**/
#define AES_BLOCK_SIZE 256

/**
 * Create an 256 bit key and IV using the supplied key_data. salt can be added for taste.
 * Fills in the encryption and decryption ctx objects and returns 0 on success
 **/
int aes_init(unsigned char *key_data, int key_data_len, unsigned char *salt, EVP_CIPHER_CTX *e_ctx, EVP_CIPHER_CTX *d_ctx) {
  int i, nrounds = 5;
  unsigned char key[32], iv[32];

  /*
   * Gen key & IV for AES 256 CBC mode. A SHA1 digest is used to hash the supplied key material.
   * nrounds is the number of times the we hash the material. More rounds are more secure but
   * slower.
   */
  i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), salt, key_data, key_data_len, nrounds, key, iv);
  if (i != 32) {
    printf("Key size is %d bits - should be 256 bits\n", i);
    return -1;
  }

  EVP_CIPHER_CTX_init(e_ctx);
  EVP_EncryptInit_ex(e_ctx, EVP_aes_256_cbc(), NULL, key, iv);
  EVP_CIPHER_CTX_init(d_ctx);
  EVP_DecryptInit_ex(d_ctx, EVP_aes_256_cbc(), NULL, key, iv);

  return 0;
}

/*
 * Encrypt *len bytes of data
 * All data going in & out is considered binary (unsigned char[])
 */
unsigned char *aes_encrypt(EVP_CIPHER_CTX *e, unsigned char *plaintext, int *len) {
  /* max ciphertext len for a n bytes of plaintext is n + AES_BLOCK_SIZE -1 bytes */
  int c_len = *len + AES_BLOCK_SIZE, f_len = 0;
  unsigned char *ciphertext = malloc(c_len);

  /* allows reusing of 'e' for multiple encryption cycles */
  EVP_EncryptInit_ex(e, NULL, NULL, NULL, NULL);

  /* update ciphertext, c_len is filled with the length of ciphertext generated,
    *len is the size of plaintext in bytes */
  EVP_EncryptUpdate(e, ciphertext, &c_len, plaintext, *len);

  /* update ciphertext with the final remaining bytes */
  EVP_EncryptFinal_ex(e, ciphertext+c_len, &f_len);

  *len = c_len + f_len;
  return ciphertext;
}

/*
 * Decrypt *len bytes of ciphertext
 */
unsigned char *aes_decrypt(EVP_CIPHER_CTX *e, unsigned char *ciphertext, int *len) {
  /* because we have padding ON, we must allocate an extra cipher block size of memory */
  int p_len = *len, f_len = 0;
  unsigned char *plaintext = malloc(p_len + AES_BLOCK_SIZE);

  EVP_DecryptInit_ex(e, NULL, NULL, NULL, NULL);
  EVP_DecryptUpdate(e, plaintext, &p_len, ciphertext, *len);
  EVP_DecryptFinal_ex(e, plaintext+p_len, &f_len);

  *len = p_len + f_len;
  return plaintext;
}



/*
 * (unportable) functions to turn on/off terminal echo
 * using termios functions. might compile however on
 * most unices, tested on FreeBSD only.
 */

static struct termios stored_settings;

void echo_off() {
  struct termios new_settings;
  tcgetattr(0,&stored_settings);
  new_settings = stored_settings;
  new_settings.c_lflag &= (~ECHO);
  tcsetattr(0,TCSANOW,&new_settings);
}

void echo_on() {
  tcsetattr(0,TCSANOW,&stored_settings);
}


/*
 * read a line from stdin, return without
 * trailing \n or NULL if something went
 * wrong
 */
char *get_stdin() {
  char *line = NULL;
  size_t linecap = 0;
  ssize_t linelen;
  linelen = getline(&line, &linecap, stdin);

  if (linelen < 0) {
    return NULL;
  }
  else {
    line[linelen - 1] = '\0'; // remove newline at end
    return line;
  }
}

/*
 * turn off terminal echo, ask for a passphrase
 * and turn it on again
 */
char * get_passphrase(char *prompt) {
  printf("%s: ", prompt);
  echo_off();
  char *line = get_stdin();
  echo_on();
  printf("\n");
  return line;
}

/*
 * Get and store one header in certificate
 */
static int s_get_meta (zcert_t *cert, char *prompt, char *name) {
    printf ("%s ", prompt);
    char *value = get_stdin();

    if (value == NULL)
      return -1;
    else
      zcert_set_meta (cert, name, value);
    return 0;
}

/*
 * (internal debug) function to print a curve key in hex
 */
void prkey(unsigned char *k) {
  int i;

  for (i = 0;i < 32;++i) printf("%02x",(unsigned int) k[i]);

  printf("\n");
}

/*
 * Encrypt the secret key of the given certificate
 * using AES256. Encryption functions are from OpenSSL's
 * libcrypto.
 */
zcert_t *zcert_encrypt_secret(zcert_t *cert, char *key_data) {
  EVP_CIPHER_CTX en, de;
  unsigned int salt[] = {12345, 54321}; // hardcoded salt for the moment
  int i;
  int key_data_len = strlen(key_data);

  /* gen key and iv. init the cipher ctx object */
  if (aes_init(key_data, key_data_len, (unsigned char *)&salt, &en, &de)) {
    fprintf(stderr, "Couldn't initialize AES cipher\n");
    return NULL;
  }

  /* fetch secret and public keys in raw binary form */
  uint8_t secret [32];
  uint8_t public [32];
  zmq_z85_decode(secret, zcert_secret_txt(cert));
  zmq_z85_decode(public, zcert_public_txt(cert));

  unsigned char *ciphertext;
  int len = 33;

  /* actually encrypt the secret */
  unsigned char *encrypted_secret = aes_encrypt(&en, (unsigned char *)secret, &len);

  //prkey(secret);
  //prkey(encrypted_secret);

  // now, we're cheating:
  // we create a new [fake] certificate with the
  // encrypted key:
  zcert_t *c = zcert_new_from(public, encrypted_secret);

  // copy meta from the original
  zcert_set_meta(c, "name",  zcert_meta(cert, "name"));
  zcert_set_meta(c, "email", zcert_meta(cert, "email"));
  zcert_set_meta(c, "org",   zcert_meta(cert, "org"));

  // tell that this one is encrypted
  zcert_set_meta(c, "aes256-encrypted-secret", "enabled");

  return c;
}


/*
 * Decrypt the secret key of the given certificate
 * using AES256. Encryption functions are from OpenSSL's
 * libcrypto.
 */
zcert_t *zcert_decrypt_secret(zcert_t *cert) {
  EVP_CIPHER_CTX en, de;
  unsigned int salt[] = {12345, 54321}; // hardcoded salt for the moment
  int i;
  char *key_data;
  int key_data_len; // = strlen(key_data);

  /* check if it is encrypted anyway */
  char *aes_meta = zcert_meta(cert, "aes256-encrypted-secret");
  if(strncmp(aes_meta, "enabled", 80) != 0) {
    // nope
    return cert;
  }
  else {
    key_data = get_passphrase("Enter passphrase");
    if(key_data == NULL || strlen(key_data) <= 0) {
      fprintf(stderr, "Sorry, you need to enter a passphrase in order to decrypt the secret key!\n");
      return NULL;
    }
  }

  key_data_len = strlen(key_data);

  /* gen key and iv. init the cipher ctx object */
  if (aes_init(key_data, key_data_len, (unsigned char *)&salt, &en, &de)) {
    fprintf(stderr, "Couldn't initialize AES cipher\n");
    return NULL;
  }

  /* fetch secret and public keys in raw binary form */
  uint8_t secret [32];
  uint8_t public [32];
  zmq_z85_decode(secret, zcert_secret_txt(cert));
  zmq_z85_decode(public, zcert_public_txt(cert));

  unsigned char *ciphertext;
  int len = 33;

  /* actually decrypt the secret */
  unsigned char* clear_secret = (char *)aes_decrypt(&de, secret, &len);
  //prkey(secret);
  //prkey(encrypted_secret);

  // now, we're cheating:
  // we create a new [fake] certificate with the
  // encrypted key:
  zcert_t *c = zcert_new_from(public, clear_secret);

  // copy meta from the original
  zcert_set_meta(c, "name",  zcert_meta(cert, "name"));
  zcert_set_meta(c, "email", zcert_meta(cert, "email"));
  zcert_set_meta(c, "org",   zcert_meta(cert, "org"));

  // tell that this one is encrypted
  zcert_set_meta(c, "aes256-encrypted-secret", "disabled");

  return c;
}



void usage() {
  fprintf(stderr, "Usage: curve-genkey [options]\n");
  fprintf(stderr,  "Options:\n");
  fprintf(stderr,  "  -f <keyfile>    Filename for the key, default: 'id_curve25519'.\n");
  fprintf(stderr,  "  -n <name>       Your name\n");
  fprintf(stderr,  "  -m <mail>       Your email address\n");
  fprintf(stderr,  "  -o <org>        Your organization\n");
  fprintf(stderr,  "  -y              Read private key file and print public key, requires -s\n");
  fprintf(stderr,  "  -s <secretfile> File containing a secret key\n");
  fprintf(stderr,  "  -c              Don't encrypt the secret key (CZMQ default)\n");
  exit(EXIT_FAILURE);
}


int main (int argc, char **argv)  {
  int opt;
  char *filename = "id_curve25519";
  char *secretfile = "";
  char *name     = "";
  char *mail     = "";
  char *org      = "";
  int export     = 0;
  int unsecure   = 0;
  int filenamegiven = 0;

  while (1) {
    opt = getopt(argc, argv, "f:n:m:o:hys:");

    if(opt == -1) {
      break;
    }

    switch (opt)  {
      case 'y':
    export = 1;
    break;
      case 'c':
    unsecure = 1;
    break;
      case 'f':
    filename = optarg;
    filenamegiven = 1;
    break;
      case 's':
    secretfile = optarg;
    break;  
      case 'n':
    name = optarg;
    break;
      case 'm':
    mail = optarg;
    break;
      case 'o':
    org = optarg;
    break;
      case 'h':
    usage();
      default:
    usage();
    }
  }

  if(export) {
    // export the public key from a private one
    if(secretfile[0] != '\0' && filename[0] != '0' && filenamegiven) {
      if(! zfile_exists(secretfile)) {
    fprintf(stderr, "Private key file %s doesn't exist!\n", secretfile);
    return -1;
      }
      else {
    zcert_t *priv      = zcert_load(secretfile);
    zcert_t *privclear = zcert_decrypt_secret(priv); // might return the same if unencrypted
    zcert_save_public(privclear, filename);
    printf ("Public key from Curve25519 certificate %s exported to %s\n", secretfile, filename);
    return 0;
      }
    }
    else {
      fprintf(stderr, "Parameter -s <secretkeyfile> (input) and -f <publickeyfile> (output) required for -y!\n");
      return -1;
    }
  }

  /* make sure we don't destroy something */
  if(zfile_exists(filename)) {
    printf("Key file %s already exists. Overwrite [Ny]? ", filename);
    char *c = get_stdin();
    if(strncmp(c, "y", 80) != 0) {
      printf("abort\n");
      return 0;
    }
  }

  printf ("Creating new Curve25519 certificate %s\n", filename);

  zcert_t *cert = zcert_new ();

  if(name[0] == '\0') {
    if(s_get_meta (cert, "Enter your full name:", "name"))
      return -1;
  }
  else {
    zcert_set_meta(cert, "name", name);
  }

  if(mail[0] == '\0') {
    if(s_get_meta (cert, "Enter your email address:", "email"))
      return -1;
  }
  else {
    zcert_set_meta(cert, "email", mail);
  }

  if(org[0] == '\0'){
    if(s_get_meta (cert, "Enter your organization:", "organization"))
      return -1;
  }
  else {
    zcert_set_meta(cert, "org", org);
  }

  char *timestr = zclock_timestr ();
  zcert_set_meta (cert, "created-by", "curve-genkey");
  zcert_set_meta (cert, "date-created", timestr);
  free (timestr);

  char *sec = "Unsecure";

  if (unsecure) {
    /* create an original CZMQ cert with unencrypted secret key */
    zcert_save (cert, filename);
  }
  else {
    char *pass1 = get_passphrase("Enter a passphrase, leave empty for unprotected key");
    if(pass1 != NULL && strlen(pass1) > 0) {
      char *pass2 = get_passphrase("                           Enter a passphrase again");
      if(strncmp(pass1, pass2, 80) == 0) {
    zcert_t *encrypted = zcert_encrypt_secret(cert, pass1);
    if(encrypted != NULL) {
      zcert_save (encrypted, filename);
      sec = "Encrypted";
    }
    else {
      return -1;
    }
      }
      else {
    fprintf(stderr, "Passphrases were not identical, please repeat!\n");
    return -1;
      }
    }
    else {
      /* user just pressed enter, so make default CZMQ unencrypted cert */
      zcert_save (cert, filename);
    }
  }

  printf ("%s Curve25519 certificate created in %s and %s_secret\n", sec, filename, filename);

  zcert_destroy (&cert);

  return 0;
}

Remove zhash / zfile etc

It seems like some of these are not even used internally (that I can grep at least), and not that they're bad or anything but they could easily be moved into a different library so czmq could be more focused

vsnprintf Return Values cause err

in s_send_string
int required = vsnprintf (string, size, format, argptr);
if (required >= size) {
size = required + 1;
string = (char *) realloc (string, size);
vsnprintf (string, size, format, argptr);
}
but in windows, the required is -1,
there is a solution in
http://perfec.to/vsnprintf/

Defining inline __inline causes MSVC 2012 error

Why does czmq redefine inline? This causes MSVC compile errors and when removed doesn't have ill effect.

1>C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\xkeycheck.h(199): warning C4005: 'inline' : macro redefinition
1> c:\czmq\include\czmq_prelude.h(395) : see previous definition of 'inline'
1>C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\xkeycheck.h(242): fatal error C1189: #error : The C++ Standard Library forbids macroizing keywords. Enable warning C4005 to find the forbidden macro.
1> Generating Code...

zloop gets confused if you create timer with same arg as expired timer

Problem: if a timer expires (either by default, or by calling zloop_timer_end(), and you add a new timer with the same argument, zloop will destroy the new timer at the same time as it destroys the expired one.

Solution: when reaping zombie timers, only reap the first one. Secondly, add new timers to end of timer list, not start.

Destroying an inproc socket aborts CZMQ

When you close an inproc socket, czmq aborts.

Example: http://gist.github.com/jlopezr/5606165

Assertion failed: (rc == 0 || errno == ETERM), function zsocket_set_linger, file zsockopt.c, line 888.
Abort trap: 6

zmq_set_sockopt return ENOTSOCK, logically as inproc socket is not a network socket. I solved this issue ignoring also this possible return. It will be nice to ignore this error only when the socket is connected/bound using inproc transport but ZMQ seems not to provide externally this information.

new disconnect functionalities breaks jenkins builds

Czmq doesn't compile cleanly with libzmq2.x

cc1: warnings being treated as errors
zsocket.c: In function ‘zsocket_disconnect’:
zsocket.c:139: error: implicit declaration of function ‘zmq_disconnect’
make[2]: *** [zsocket.lo] Error 1
make[2]: Leaving directory `<http://build.zero.mq/job/czmq-master_libzmq2-x_GCC-debian/ws/src'>
make[1]: *** [all] Error 2
make[1]: Leaving directory `<http://build.zero.mq/job/czmq-master_libzmq2-x_GCC-debian/ws/src'>
make: *** [all-recursive] Error 1
Build step 'Execute shell' marked build as failure
Skipping Cobertura coverage report as build was not UNSTABLE or better ...

Solution:

Add pre procesor check to avoid this warning.

Memory leak/attack vector

Summary: It seems there is a memory leak or some sort of unexpected behavior in czmq where server sockets (such as Router or Publish) will grow indefinitely in size as more and more clients connect and disconnect. It seems to grow faster when clients server an identity (or subscription), but this could just be my subjective observation, I don't have any proof at the moment. While exclusive (to my knowledge) to czmq anyone wanting to crash your service or API could make use of this method.

To reproduce run the 'all_in_one' program or compile and run 'czmq_leak_s' and 'czmq_leak_c' side by side so see that growth occurs on t he server side and not as a consequence of building up and tearing down contexts/sockets.en

Details:
OS: Debian 6.0.7
Compiler: gcc (Debian 4.4.5-8) 4.4.5
Valgrind: valgrind-3.6.0.SVN-Debian

ZMQ version is 3.2.3
CZMQ version is 1.4.0

Example: https://gist.github.com/JustonDavies/5266122

Notes: A peer made a program to attempt to reproduce this using just the standard zmq.h binding and was unable to reproduce the issue. Link can be found on the above Gist and also at https://gist.github.com/deepcube/5417288

Create CMake build file

Currently I've got a cmake build file. I pass in the libzmq directory manually and install to a ../lib directory. I hope you can improve on it.

cmake_minimum_required(VERSION 2.8)

project( czmq )

set(SOURCES_files_Source_Files
  src/zbeacon.c
  src/zclock.c
  src/zconfig.c
  src/zctx.c
  src/zfile.c
  src/zframe.c
  src/zhash.c
  src/zlist.c
  src/zloop.c
  src/zmsg.c
  src/zmutex.c
  src/zsocket.c
  src/zsockopt.c
  src/zstr.c
  src/zsys.c
  src/zthread.c
  src/ztree.c
)
source_group("Source Files" FILES ${SOURCES_files_Source_Files})

set(SOURCES_Source_Files
  ${SOURCES_files_Source_Files}
)

set(SOURCES_files_Header_Files
  include/czmq.h
  include/czmq_prelude.h
  include/zbeacon.h
  include/zclock.h
  include/zconfig.h
  include/zctx.h
  include/zfile.h
  include/zframe.h
  include/zhash.h
  include/zlist.h
  include/zloop.h
  include/zmsg.h
  include/zmutex.h
  include/zsocket.h
  include/zsockopt.h
  include/zstr.h
  include/zsys.h
  include/zthread.h
  include/ztree.h
)
source_group("Header Files" FILES ${SOURCES_files_Header_Files})

set(SOURCES_Header_Files
  ${SOURCES_files_Header_Files}
)

set(SOURCES_
  ${SOURCES_Source_Files}
  ${SOURCES_Header_Files}
)

set( WITH_LIBZMQ . )

include_directories(
  ../libzmq/include
  include
  ${CMAKE_INSTALL_PREFIX}/include
  ${WITH_LIBZMQ}
)

set_source_files_properties(${SOURCES_files_Source_Files} PROPERTIES LANGUAGE CXX )

add_library ( czmq ${SOURCES_} )

install ( TARGETS czmq LIBRARY DESTINATION lib ARCHIVE DESTINATION lib )
install ( FILES ${SOURCES_files_Header_Files} DESTINATION include )

man pages belong to section 3

Problem: IMHO all man pages (except czmq.7) of czmq belong to section 3.

Solution: change doc/Makefile.am accordingly.

I can prepare a patch, if there is no disagreement.

zmsg_unwrap asserts on empty or single frame zmsg

This is due to it unconditionally calling zframe_size on the empty frame. zframe_size asserts on NULL argument.

Is this behaviour desired? If not, a trivial check for empty could be added to zmsg.c:403.

Compilation issue on Mingw32: redeclared without dllimport attribute

Here's the log:

$ ./configure --prefix=/usr/local --with-libzmq=/usr/local
$ make
*snip*
make[2]: Entering directory `/g/Dev/czmq-1.3.1/src'
/bin/sh ../libtool --tag=CC   --mode=compile gcc -std=gnu99 -DHAVE_CONFIG_H -I. -I../include  -Werror -Wall -D_REENTRANT -D_THREAD_SAFE   -I/usr/local/include -g -O2 -MT zclock.lo -MD -MP -MF .deps/zclock.Tpo -c -o zclock.lo zclock.c
libtool: compile:  gcc -std=gnu99 -DHAVE_CONFIG_H -I. -I../include -Werror -Wall -D_REENTRANT -D_THREAD_SAFE -I/usr/local/include -g -O2 -MT zclock.lo -MD -MP -MF .deps/zclock.Tpo -c zclock.c  -DDLL_EXPORT -DPIC -o .libs/zclock.o
libtool: compile:  gcc -std=gnu99 -DHAVE_CONFIG_H -I. -I../include -Werror -Wall -D_REENTRANT -D_THREAD_SAFE -I/usr/local/include -g -O2 -MT zclock.lo -MD -MP -MF .deps/zclock.Tpo -c zclock.c -o zclock.o >/dev/null 2>&1
make[2]: *** [zclock.lo] Error 1

Upon running the same gcc command by hand, I get these error messages:

zclock.c:70:1: error: 'zclock_sleep' redeclared without dllimport attribute: previous dllimport ignored [-Werror=attributes]
zclock.c:97:1: error: 'zclock_time' redeclared without dllimport attribute: previous dllimport ignored [-Werror=attributes]
zclock.c:117:1: error: 'zclock_log' redeclared without dllimport attribute: previous dllimport ignored [-Werror=attributes]
cc1.exe: all warnings being treated as errors

I don't know how harmful that warning is (never really built DLLs on Windows myself), but with -Werror it does cause the build to fail.

As for my setup, here it is:

  • GCC 4.7.2, 32-bit
  • autotools 2.68
  • GNU m4 1.4.14

That's building czmq 1.3.2, fresh out the release cutter :)

zlist_autofree uses strdup

Can strdup be used for something other than strings?

zlist.txt indicates to use zlist_autofree for any kind of object.

blocking sockets not interrupted on ctrl+c

Using libzmq 3.3.0 + czmq 1.4.2

When I hit CTRL+C, zctx_interrupted is set to true however blocking sockets in forked threads do not return an error or NULL.

Here's some code which demonstrates the issue:

#include "czmq.h"
static void task (void *args, zctx_t *ctx, void *pipe){
        while(true){
                char *txt = zstr_recv(pipe);
                if (!txt){
                        printf("zmsg_recv error: %s\n",zmq_strerror(errno));
                        break;
                } else {
                        printf("txt: %s\n",txt);
                }
                free(txt);
        }
}

int main(int argc,char ** argv){
        zctx_t * ctx = zctx_new();
        void * pipe = zthread_fork(ctx, task, NULL);
        printf("Starting\n");
        while(!zctx_interrupted){
                zclock_sleep(1000);
        }
        printf("Send to pipe\n");
        zstr_send (pipe, "This text should never be printed to stdout!");
        zclock_sleep(1000);
        zctx_destroy(&ctx);
        printf("Exit\n");
        return(EXIT_SUCCESS);
}

When I run this code I get the following output:

 ./test
Starting
^CSend to pipe
txt: This text should never be printed to stdout!
zmsg_recv error: Context was terminated
Context was terminated
Exit

Missing tags for past releases

It looks like tags for 1.1.0 and the 1.3.X series of releases have not been made. If possible, it would be really handy to have tags for these in git as a reference point.

auth class doesn't work

Hello,

I'm trying to get the czmq examples to work. I took the ironhouse.c and separated it into 2 different programs (the server and the client). Here's how they look:

The client:

#include <czmq.h>
/* CLIENT */
int main (void) {
  zctx_t *ctx = zctx_new ();
  assert (ctx);
  void *client = zsocket_new (ctx, ZMQ_PULL);
  assert (client);
  int rc = zsocket_connect (client, "tcp://127.0.0.1:9000");
  assert (rc == 0);
  char *message = zstr_recv (client);
  assert (streq (message, "Hello"));
  free (message);
  puts ("Ironhouse test OK");
  zctx_destroy (&ctx);
  return 0;
}

The server:

#include <czmq.h>
/* SERVER */
int main (void) {
  zctx_t *ctx = zctx_new ();
  assert(ctx);
  zctx_set_linger (ctx, 100);
  zauth_t *auth = zauth_new (ctx);
  assert(auth);
  zauth_set_verbose (auth, true);
  zauth_allow (auth, "127.0.0.2");
  void *server = zsocket_new (ctx, ZMQ_PUSH);
  assert (server);
  int rc = zsocket_bind (server, "tcp://*:9000");
  assert (rc != -1);
  zstr_send (server, "Hello");
  zauth_destroy (&auth);
  zctx_destroy (&ctx);
  return 0;
}

The problem is, that it works. Please note the ip address in zauth_allow(): it doesn't exist and I'd expect to get a DENIED. Instead the server prints nothing and just passes the client through as if there's no auth object at all. And the client happily prints "Ironhouse test OK".

The unmodified ironhouse.c example as well as the others work as they should. If I change there the address, I get the deny. So, it always works if server and client reside within the same process. But if I separate them into different processes, it ceases to work.

I've got no idea what might be wrong.

My setup:
czmq-2.0.1
zeromq-4.0.0
libsodium-0.4.3
FreeBSD 9.0-RELEASE
gcc version 4.2.1 20070831 patched [FreeBSD](from base)

As a sidenote (I'm not sure if this makes any difference here): in order to compile zeromq, I had to manually patch the generated makefile and remove the "-pedantic" gcc-flag. It caused gcc to throw errors about "long long" not being ISO C++ compliant (there are some unsigned long long's in /usr/include/*, which I cannot change).

Any idea?

Thanks in advance,
Tom

Improve property functions

  • Naming would work better if property functions started with zsocket_ instead of zsockopt_
  • Some 0MQ/3.1 properties are missing from the generated code
  • Generated code for blob properties is incomplete (missing function to get property)

CZMQ needs to provide a version constant

Problem: CZMQ doesn't export a version constant and since its API changed (added consts), this makes it painful for apps who have been using older versions.

Solution: define CZMQ_VERSION macros in czmq.h

Stop using 'socket' in sample code

Problem: when I copy/paste sample code that has a variable 'socket' into code that is using real socket variables called something else, the results build without trouble but die weirdly at runtime. Cause; 'socket' is a function.

Solution: ban the use of 'socket' as variable in CZMQ. As alternative I've used 'zocket' everywhere.

zhash_rename - deletes but not call free_fn

I noticed that if new_key points to an already existing item, then the item pointed to by old_key gets deleted, but only in a soft way:- s_item_destroy doesn't call the free_fn. This could lead to memory leaks.

This might be by design, or it might be an oversight. If it is a bug, it seems pretty easy to fix:- just move the s_item_destroy call into the if statement and call with hard or soft as appropriate.

child thread, zsocket_set_linger assert error,when main thread call zctx_destroy (&ctx);

in Windows platform.
when main thread call zctx_destroy (&ctx), the child thread created by zthread_fork, cause assert false in zsocket_set_linger();

I am not clear the zthread lib, so I add
void * child = zthread_fork(ctx, client_task, "child1");
......
zstr_send(child,"DELETE"); //the client_task handle the DELETE cmd
char * str = zstr_recv(child);
free(str);
zctx_destroy (&ctx);

use zstr_recv to wait the client_task finish.
work like join.

is there a fun works like zthread_join.

API should not change depending on 0MQ version

Problem: choice to make zsocket_disconnect disappear and appear according to 0MQ version is somewhat... questionable.

Solution: keep the API the same no matter what the 0MQ version; if 0MQ doesn't implement disconnect, return -1.

small memory leak

writing my new app using boost, i detected a small memory leak in czmq. Just creating a context and destroying it again, leaves two blocks.

Detected memory leaks!
Dumping objects ->
{912} normal block at 0x01CA4088, 16 bytes long.
Data: < > 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
{911} normal block at 0x01CAEE08, 24 bytes long.
Data: < w5 @ > 20 77 35 02 88 40 CA 01 01 00 00 00 01 00 00 00

This is on Intel11.1 Compiler x86 with current boost library.

I have not yet had time to look closer, but maybe someone already knows why this is. It is not highly relevant since it does not grow obviously, but it is annoying not to have a clean test run and even worse having to communicate this to all other devs.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.