void zcert_test (bool verbose) { printf (" * zcert: "); #if (ZMQ_VERSION_MAJOR == 4) // @selftest // Create temporary directory for test files # define TESTDIR ".test_zcert" zsys_dir_create (TESTDIR); // Create a simple certificate with metadata zcert_t *cert = zcert_new (); # if defined (HAVE_LIBSODIUM) zcert_set_meta (cert, "email", "*****@*****.**"); zcert_set_meta (cert, "name", "Pieter Hintjens"); zcert_set_meta (cert, "organization", "iMatix Corporation"); zcert_set_meta (cert, "version", "%d", 1); assert (streq (zcert_meta (cert, "email"), "*****@*****.**")); zlist_t *keys = zcert_meta_keys (cert); assert (zlist_size (keys) == 4); zlist_destroy (&keys); // Check the dup and eq methods zcert_t *shadow = zcert_dup (cert); assert (zcert_eq (cert, shadow)); zcert_destroy (&shadow); // Check we can save and load certificate zcert_save (cert, TESTDIR "/mycert.txt"); assert (zsys_file_exists (TESTDIR "/mycert.txt")); assert (zsys_file_exists (TESTDIR "/mycert.txt_secret")); // Load certificate, will in fact load secret one shadow = zcert_load (TESTDIR "/mycert.txt"); assert (shadow); assert (zcert_eq (cert, shadow)); zcert_destroy (&shadow); // Delete secret certificate, load public one int rc = zsys_file_delete (TESTDIR "/mycert.txt_secret"); assert (rc == 0); shadow = zcert_load (TESTDIR "/mycert.txt"); // 32-byte null key encodes as 40 '0' characters assert (streq (zcert_secret_txt (shadow), "0000000000000000000000000000000000000000")); zcert_destroy (&shadow); zcert_destroy (&cert); # else // Libsodium isn't installed; should have returned NULL assert (cert == NULL); # endif // Delete all test files zdir_t *dir = zdir_new (TESTDIR, NULL); zdir_remove (dir, true); zdir_destroy (&dir); // @end #endif printf ("OK\n"); }
static void s_load_certs_from_disk (zcertstore_t *self) { s_empty_store (self); zdir_t *dir = zdir_new (self->location, NULL); if (dir) { // Load all certificates including those in subdirectories zfile_t **filelist = zdir_flatten (dir); uint index; for (index = 0;; index++) { zfile_t *file = filelist [index]; if (!file) break; // End of list if (zfile_is_regular (file)) { zcert_t *cert = zcert_load (zfile_filename (file, NULL)); if (cert) zcertstore_insert (self, &cert); } } zdir_flatten_free (&filelist); self->modified = zdir_modified (dir); self->count = zdir_count (dir); self->cursize = zdir_cursize (dir); zdir_destroy (&dir); } }
static void s_check_directory (s_agent_t *self) { // Get latest snapshot and build a patches list for any changes // All patches are built using a virtual path starting at "/" zdir_t *dir = zdir_new (self->path, NULL); zlist_t *patches = zdir_diff (self->dir, dir, "/"); // Drop old directory and replace with latest version zdir_destroy (&self->dir); self->dir = dir; while (zlist_size (patches)) { zdir_patch_t *patch = (zdir_patch_t *) zlist_pop (patches); if (zdir_patch_op (patch) == patch_create) { // Shout new files to DROPS group // Stupidest possible approach: send whole file as one frame // Truncate file at arbitrary limit of 10MB zfile_t *file = zdir_patch_file (patch); if (zfile_input (file) == 0) { zchunk_t *chunk = zfile_read (file, 10 * 1024 * 1024, 0); assert (chunk); zmsg_t *msg = zmsg_new (); zmsg_addstr (msg, "CREATE"); zmsg_addstr (msg, zdir_patch_vpath (patch)); zmsg_add (msg, zframe_new (zchunk_data (chunk), zchunk_size (chunk))); zchunk_destroy (&chunk); zyre_shout (self->zyre, "DROPS", &msg); } } zdir_patch_destroy (&patch); } zlist_destroy (&patches); }
void zdir_remove (zdir_t *self, bool force) { // If forced, remove all subdirectories and files if (force) { zfile_t *file = (zfile_t *) zlist_pop (self->files); while (file) { zfile_remove (file); zfile_destroy (&file); file = (zfile_t *) zlist_pop (self->files); } zdir_t *subdir = (zdir_t *) zlist_pop (self->subdirs); while (subdir) { zdir_remove (subdir, force); zdir_destroy (&subdir); subdir = (zdir_t *) zlist_pop (self->subdirs); } self->cursize = 0; self->count = 0; } // Remove if empty if (zlist_size (self->files) == 0 && zlist_size (self->subdirs) == 0) zsys_dir_delete (self->path); }
static bool mount_refresh (mount_t *self, server_t *server) { bool activity = false; // Get latest snapshot and build a patches list for any changes zdir_t *latest = zdir_new (self->location, NULL); zlist_t *patches = zdir_diff (self->dir, latest, self->alias); // Drop old directory and replace with latest version zdir_destroy (&self->dir); self->dir = latest; // Copy new patches to clients' patches list sub_t *sub = (sub_t *) zlist_first (self->subs); while (sub) { zdir_patch_t *patch = (zdir_patch_t *) zlist_first (patches); while (patch) { sub_patch_add (sub, patch); patch = (zdir_patch_t *) zlist_next (patches); activity = true; } sub = (sub_t *) zlist_next (self->subs); } // Destroy patches, they've all been copied while (zlist_size (patches)) { zdir_patch_t *patch = (zdir_patch_t *) zlist_pop (patches); zdir_patch_destroy (&patch); } zlist_destroy (&patches); return activity; }
void zcertstore_test (bool verbose) { printf (" * zcertstore: "); if (verbose) printf ("\n"); // @selftest // Create temporary directory for test files # define TESTDIR ".test_zcertstore" zsys_dir_create (TESTDIR); // Load certificate store from disk; it will be empty zcertstore_t *certstore = zcertstore_new (TESTDIR); assert (certstore); // Create a single new certificate and save to disk zcert_t *cert = zcert_new (); assert (cert); char *client_key = strdup (zcert_public_txt (cert)); assert (client_key); zcert_set_meta (cert, "name", "John Doe"); zcert_save (cert, TESTDIR "/mycert.txt"); zcert_destroy (&cert); // Check that certificate store refreshes as expected cert = zcertstore_lookup (certstore, client_key); assert (cert); assert (streq (zcert_meta (cert, "name"), "John Doe")); // Test custom loader test_loader_state *state = (test_loader_state *) zmalloc (sizeof (test_loader_state)); state->index = 0; zcertstore_set_loader (certstore, s_test_loader, s_test_destructor, (void *)state); #if (ZMQ_VERSION_MAJOR >= 4) cert = zcertstore_lookup (certstore, client_key); assert (cert == NULL); cert = zcertstore_lookup (certstore, "abcdefghijklmnopqrstuvwxyzabcdefghijklmn"); assert (cert); #endif free (client_key); if (verbose) zcertstore_print (certstore); zcertstore_destroy (&certstore); // Delete all test files zdir_t *dir = zdir_new (TESTDIR, NULL); assert (dir); zdir_remove (dir, true); zdir_destroy (&dir); #if defined (__WINDOWS__) zsys_shutdown(); #endif // @end printf ("OK\n"); }
static void s_sub_free (void *data) { zdir_watch_sub_t *sub = (zdir_watch_sub_t *) data; zdir_destroy (&sub->dir); freen (sub); }
static int s_on_read_timer (zloop_t *loop, int timer_id, void *arg) { zdir_watch_t *watch = (zdir_watch_t *) arg; void *data; for (data = zhash_first (watch->subs); data != NULL; data = zhash_next (watch->subs)) { zdir_watch_sub_t *sub = (zdir_watch_sub_t *) data; zdir_t *new_dir = zdir_new (zdir_path (sub->dir), NULL); if (!new_dir) { if (watch->verbose) zsys_error ("zdir_watch: Unable to create new zdir for path %s", zdir_path (sub->dir)); continue; } // Determine if anything has changed. zlist_t *diff = zdir_diff (sub->dir, new_dir, ""); // Do memory management before error handling... zdir_destroy (&sub->dir); sub->dir = new_dir; if (!diff) { if (watch->verbose) zsys_error ("zdir_watch: Unable to create diff for path %s", zdir_path (sub->dir)); continue; } if (zlist_size (diff) > 0) { if (watch->verbose) { zdir_patch_t *patch = (zdir_patch_t *) zlist_first (diff); zsys_info ("zdir_watch: Found %d changes in %s:", zlist_size (diff), zdir_path (sub->dir)); while (patch) { zsys_info ("zdir_watch: %s %s", zfile_filename (zdir_patch_file (patch), NULL), zdir_patch_op (patch) == ZDIR_PATCH_CREATE? "created": "deleted"); patch = (zdir_patch_t *) zlist_next (diff); } } if (zsock_send (watch->pipe, "sp", zdir_path (sub->dir), diff) != 0) { if (watch->verbose) zsys_error ("zdir_watch: Unable to send patch list for path %s", zdir_path (sub->dir)); zlist_destroy (&diff); } // Successfully sent `diff` list - now owned by receiver } else { zlist_destroy (&diff); } } return 0; }
void hydra_post_test (bool verbose) { printf (" * hydra_post: "); if (verbose) printf ("\n"); // @selftest // Simple create/destroy test zsys_dir_create (".hydra_test"); zsys_dir_change (".hydra_test"); hydra_post_t *post = hydra_post_new ("Test post"); assert (post); hydra_post_set_content (post, "Hello, World"); assert (streq (hydra_post_mime_type (post), "text/plain")); char *content = hydra_post_content (post); assert (content); assert (streq (content, "Hello, World")); zstr_free (&content); int rc = hydra_post_save (post, "testpost"); assert (rc == 0); hydra_post_destroy (&post); post = hydra_post_load ("testpost"); assert (post); assert (hydra_post_content_size (post) == 12); if (verbose) hydra_post_print (post); content = hydra_post_content (post); assert (content); assert (streq (content, "Hello, World")); zstr_free (&content); zchunk_t *chunk = hydra_post_fetch ( post, hydra_post_content_size (post), 0); assert (chunk); assert (zchunk_size (chunk) == 12); zchunk_destroy (&chunk); hydra_post_t *copy = hydra_post_dup (post); assert (streq (hydra_post_ident (copy), hydra_post_ident (post))); hydra_post_destroy (&post); hydra_post_destroy (©); // Delete the test directory zsys_dir_change (".."); zdir_t *dir = zdir_new (".hydra_test", NULL); assert (dir); zdir_remove (dir, true); zdir_destroy (&dir); // @end printf ("OK\n"); }
int zfile_test (bool verbose) { printf (" * zfile: "); // @selftest zfile_t *file = zfile_new (".", "bilbo"); assert (streq (zfile_filename (file, "."), "bilbo")); assert (zfile_is_readable (file) == false); zfile_destroy (&file); // Create a test file in some random subdirectory file = zfile_new ("./this/is/a/test", "bilbo"); int rc = zfile_output (file); assert (rc == 0); zchunk_t *chunk = zchunk_new (NULL, 100); zchunk_fill (chunk, 0, 100); // Write 100 bytes at position 1,000,000 in the file rc = zfile_write (file, chunk, 1000000); assert (rc == 0); zfile_close (file); assert (zfile_is_readable (file)); assert (zfile_cursize (file) == 1000100); assert (!zfile_is_stable (file)); zchunk_destroy (&chunk); zclock_sleep (1001); assert (zfile_is_stable (file)); // Check we can read from file rc = zfile_input (file); assert (rc == 0); chunk = zfile_read (file, 1000100, 0); assert (chunk); assert (zchunk_size (chunk) == 1000100); zchunk_destroy (&chunk); // Remove file and directory zdir_t *dir = zdir_new ("./this", NULL); assert (zdir_cursize (dir) == 1000100); zdir_remove (dir, true); assert (zdir_cursize (dir) == 0); zdir_destroy (&dir); // Check we can no longer read from file assert (!zfile_is_readable (file)); rc = zfile_input (file); assert (rc == -1); zfile_destroy (&file); // @end printf ("OK\n"); return 0; }
static void s_agent_destroy (s_agent_t **self_p) { assert (self_p); if (*self_p) { s_agent_t *self = *self_p; zdir_destroy (&self->dir); zyre_destroy (&self->zyre); free (self->path); free (self); *self_p = NULL; } }
zcert_t * zcertstore_lookup (zcertstore_t *self, char *public_key) { // If directory has changed, reload all certificates if (self->location) { zdir_t *dir = zdir_new (self->location, NULL); if (dir && (self->modified != zdir_modified (dir) || self->count != zdir_count (dir) || self->cursize != zdir_cursize (dir))) { s_load_certs_from_disk (self); } zdir_destroy (&dir); } return (zcert_t *) zhash_lookup (self->cert_hash, public_key); }
void drops_test (bool verbose) { printf (" * drops: "); // @selftest // Create temporary directory for test files # define TESTDIR ".test_drops" // Create two drops instances and test some to and fro zsys_dir_create (TESTDIR "/box1"); drops_t *drops1 = drops_new (TESTDIR "/box1"); zsys_dir_create (TESTDIR "/box2"); drops_t *drops2 = drops_new (TESTDIR "/box2"); // Give time for nodes to discover each other and interconnect zclock_sleep (100); FILE *output = fopen (TESTDIR "/box1/bilbo", "w"); fprintf (output, "Hello, world"); fclose (output); // Directory monitoring is once per second at present, so this gives // time for box1 to see its new file, and send it to box2 zclock_sleep (1200); char buffer [256]; FILE *input = fopen (TESTDIR "/box2/bilbo", "r"); assert (input); char *result = fgets (buffer, 256, input); assert (result == buffer); assert (streq (buffer, "Hello, world")); fclose (input); drops_destroy (&drops2); drops_destroy (&drops1); // Delete all test files zdir_t *dir = zdir_new (TESTDIR, NULL); zdir_remove (dir, true); zdir_destroy (&dir); // @end zclock_sleep (100); printf ("OK\n"); }
void zconfig_test (bool verbose) { printf (" * zconfig: "); // @selftest // Create temporary directory for test files # define TESTDIR ".test_zconfig" zsys_dir_create (TESTDIR); zconfig_t *root = zconfig_new ("root", NULL); zconfig_t *section, *item; section = zconfig_new ("headers", root); item = zconfig_new ("email", section); zconfig_set_value (item, "*****@*****.**"); item = zconfig_new ("name", section); zconfig_set_value (item, "Justin Kayce"); zconfig_put (root, "/curve/secret-key", "Top Secret"); zconfig_set_comment (root, " CURVE certificate"); zconfig_set_comment (root, " -----------------"); assert (zconfig_comments (root)); zconfig_save (root, TESTDIR "/test.cfg"); zconfig_destroy (&root); root = zconfig_load (TESTDIR "/test.cfg"); if (verbose) zconfig_save (root, "-"); char *email = zconfig_resolve (root, "/headers/email", NULL); assert (email); assert (streq (email, "*****@*****.**")); char *passwd = zconfig_resolve (root, "/curve/secret-key", NULL); assert (passwd); assert (streq (passwd, "Top Secret")); zconfig_save (root, TESTDIR "/test.cfg"); zconfig_destroy (&root); // Delete all test files zdir_t *dir = zdir_new (TESTDIR, NULL); zdir_remove (dir, true); zdir_destroy (&dir); // @end printf ("OK\n"); }
void zcertstore_test (bool verbose) { printf (" * zcertstore: "); if (verbose) printf ("\n"); // @selftest // Create temporary directory for test files # define TESTDIR ".test_zcertstore" zsys_dir_create (TESTDIR); // Load certificate store from disk; it will be empty zcertstore_t *certstore = zcertstore_new (TESTDIR); assert (certstore); // Create a single new certificate and save to disk zcert_t *cert = zcert_new (); assert (cert); char *client_key = strdup (zcert_public_txt (cert)); assert (client_key); zcert_set_meta (cert, "name", "John Doe"); zcert_save (cert, TESTDIR "/mycert.txt"); zcert_destroy (&cert); // Check that certificate store refreshes as expected cert = zcertstore_lookup (certstore, client_key); assert (cert); assert (streq (zcert_meta (cert, "name"), "John Doe")); free (client_key); if (verbose) zcertstore_print (certstore); zcertstore_destroy (&certstore); // Delete all test files zdir_t *dir = zdir_new (TESTDIR, NULL); assert (dir); zdir_remove (dir, true); zdir_destroy (&dir); // @end printf ("OK\n"); }
static void mount_destroy (mount_t **self_p) { assert (self_p); if (*self_p) { mount_t *self = *self_p; free (self->location); free (self->alias); // Destroy subscriptions while (zlist_size (self->subs)) { sub_t *sub = (sub_t *) zlist_pop (self->subs); sub_destroy (&sub); } zlist_destroy (&self->subs); zdir_destroy (&self->dir); free (self); *self_p = NULL; } }
static void s_disk_loader (zcertstore_t *certstore) { disk_loader_state *state = (disk_loader_state *)certstore->state; zdir_t *dir = zdir_new (state->location, NULL); if (dir && (state->modified != zdir_modified (dir) || state->count != zdir_count (dir) || state->cursize != (size_t) zdir_cursize (dir))) { zhashx_purge (certstore->certs); // Load all certificates including those in subdirectories zfile_t **filelist = zdir_flatten (dir); assert (filelist); zrex_t *rex = zrex_new ("_secret$"); assert (rex); uint index; for (index = 0;; index++) { zfile_t *file = filelist [index]; if (!file) break; // End of list if (zfile_is_regular (file) && !zrex_matches (rex, zfile_filename (file, NULL))) { zcert_t *cert = zcert_load (zfile_filename (file, NULL)); if (cert) zcertstore_insert (certstore, &cert); } } zdir_flatten_free (&filelist); state->modified = zdir_modified (dir); state->count = zdir_count (dir); state->cursize = zdir_cursize (dir); zrex_destroy (&rex); } zdir_destroy (&dir); }
void zdir_destroy (zdir_t **self_p) { assert (self_p); if (*self_p) { zdir_t *self = *self_p; if (self->subdirs) while (zlist_size (self->subdirs)) { zdir_t *subdir = (zdir_t *) zlist_pop (self->subdirs); zdir_destroy (&subdir); } if (self->files) while (zlist_size (self->files)) { zfile_t *file = (zfile_t *) zlist_pop (self->files); zfile_destroy (&file); } zlist_destroy (&self->subdirs); zlist_destroy (&self->files); freen (self->path); freen (self); *self_p = NULL; } }
int zauth_test (bool verbose) { printf (" * zauth: "); #if (ZMQ_VERSION_MAJOR == 4) // @selftest // Create temporary directory for test files # define TESTDIR ".test_zauth" zsys_dir_create (TESTDIR); // Install the authenticator zctx_t *ctx = zctx_new (); zauth_t *auth = zauth_new (ctx); assert (auth); zauth_set_verbose (auth, verbose); // A default NULL connection should always success, and not // go through our authentication infrastructure at all. void *server = zsocket_new (ctx, ZMQ_PUSH); void *client = zsocket_new (ctx, ZMQ_PULL); bool success = s_can_connect (ctx, &server, &client); assert (success); // When we set a domain on the server, we switch on authentication // for NULL sockets, but with no policies, the client connection // will be allowed. zsocket_set_zap_domain (server, "global"); success = s_can_connect (ctx, &server, &client); assert (success); // Blacklist 127.0.0.1, connection should fail zsocket_set_zap_domain (server, "global"); zauth_deny (auth, "127.0.0.1"); success = s_can_connect (ctx, &server, &client); assert (!success); // Whitelist our address, which overrides the blacklist zsocket_set_zap_domain (server, "global"); zauth_allow (auth, "127.0.0.1"); success = s_can_connect (ctx, &server, &client); assert (success); // Try PLAIN authentication zsocket_set_plain_server (server, 1); zsocket_set_plain_username (client, "admin"); zsocket_set_plain_password (client, "Password"); success = s_can_connect (ctx, &server, &client); assert (!success); FILE *password = fopen (TESTDIR "/password-file", "w"); assert (password); fprintf (password, "admin=Password\n"); fclose (password); zsocket_set_plain_server (server, 1); zsocket_set_plain_username (client, "admin"); zsocket_set_plain_password (client, "Password"); zauth_configure_plain (auth, "*", TESTDIR "/password-file"); success = s_can_connect (ctx, &server, &client); assert (success); zsocket_set_plain_server (server, 1); zsocket_set_plain_username (client, "admin"); zsocket_set_plain_password (client, "Bogus"); success = s_can_connect (ctx, &server, &client); assert (!success); # if defined (HAVE_LIBSODIUM) // Try CURVE authentication // We'll create two new certificates and save the client public // certificate on disk; in a real case we'd transfer this securely // from the client machine to the server machine. zcert_t *server_cert = zcert_new (); zcert_t *client_cert = zcert_new (); char *server_key = zcert_public_txt (server_cert); // Test without setting-up any authentication zcert_apply (server_cert, server); zcert_apply (client_cert, client); zsocket_set_curve_server (server, 1); zsocket_set_curve_serverkey (client, server_key); success = s_can_connect (ctx, &server, &client); assert (!success); // Test CURVE_ALLOW_ANY zcert_apply (server_cert, server); zcert_apply (client_cert, client); zsocket_set_curve_server (server, 1); zsocket_set_curve_serverkey (client, server_key); zauth_configure_curve (auth, "*", CURVE_ALLOW_ANY); success = s_can_connect (ctx, &server, &client); assert (success); // Test full client authentication using certificates zcert_apply (server_cert, server); zcert_apply (client_cert, client); zsocket_set_curve_server (server, 1); zsocket_set_curve_serverkey (client, server_key); zcert_save_public (client_cert, TESTDIR "/mycert.txt"); zauth_configure_curve (auth, "*", TESTDIR); success = s_can_connect (ctx, &server, &client); assert (success); zcert_destroy (&server_cert); zcert_destroy (&client_cert); # endif // Remove the authenticator and check a normal connection works zauth_destroy (&auth); success = s_can_connect (ctx, &server, &client); assert (success); zctx_destroy (&ctx); // Delete all test files zdir_t *dir = zdir_new (TESTDIR, NULL); zdir_remove (dir, true); zdir_destroy (&dir); // @end #endif printf ("OK\n"); return 0; }
void zconfig_test (bool verbose) { printf (" * zconfig: "); // @selftest const char *SELFTEST_DIR_RW = "src/selftest-rw"; const char *testbasedir = ".test_zconfig"; const char *testfile = "test.cfg"; char *basedirpath = NULL; // subdir in a test, under SELFTEST_DIR_RW char *filepath = NULL; // pathname to testfile in a test, in dirpath basedirpath = zsys_sprintf ("%s/%s", SELFTEST_DIR_RW, testbasedir); assert (basedirpath); filepath = zsys_sprintf ("%s/%s", basedirpath, testfile); assert (filepath); // Make sure old aborted tests do not hinder us zdir_t *dir = zdir_new (basedirpath, NULL); if (dir) { zdir_remove (dir, true); zdir_destroy (&dir); } zsys_file_delete (filepath); zsys_dir_delete (basedirpath); // Create temporary directory for test files zsys_dir_create (basedirpath); zconfig_t *root = zconfig_new ("root", NULL); assert (root); zconfig_t *section, *item; section = zconfig_new ("headers", root); assert (section); item = zconfig_new ("email", section); assert (item); zconfig_set_value (item, "*****@*****.**"); item = zconfig_new ("name", section); assert (item); zconfig_set_value (item, "Justin Kayce"); zconfig_putf (root, "/curve/secret-key", "%s", "Top Secret"); zconfig_set_comment (root, " CURVE certificate"); zconfig_set_comment (root, " -----------------"); assert (zconfig_comments (root)); zconfig_save (root, filepath); zconfig_destroy (&root); root = zconfig_load (filepath); if (verbose) zconfig_save (root, "-"); assert (streq (zconfig_filename (root), filepath)); char *email = zconfig_get (root, "/headers/email", NULL); assert (email); assert (streq (email, "*****@*****.**")); char *passwd = zconfig_get (root, "/curve/secret-key", NULL); assert (passwd); assert (streq (passwd, "Top Secret")); zconfig_savef (root, "%s/%s", basedirpath, testfile); assert (!zconfig_has_changed (root)); int rc = zconfig_reload (&root); assert (rc == 0); assert (!zconfig_has_changed (root)); zconfig_destroy (&root); // Test chunk load/save root = zconfig_new ("root", NULL); assert (root); section = zconfig_new ("section", root); assert (section); item = zconfig_new ("value", section); assert (item); zconfig_set_value (item, "somevalue"); zconfig_t *search = zconfig_locate (root, "section/value"); assert (search == item); zchunk_t *chunk = zconfig_chunk_save (root); assert (strlen ((char *) zchunk_data (chunk)) == 32); char *string = zconfig_str_save (root); assert (string); assert (streq (string, (char *) zchunk_data (chunk))); freen (string); assert (chunk); zconfig_destroy (&root); root = zconfig_chunk_load (chunk); assert (root); char *value = zconfig_get (root, "/section/value", NULL); assert (value); assert (streq (value, "somevalue")); // Test config can't be saved to a file in a path that doesn't // exist or isn't writable rc = zconfig_savef (root, "%s/path/that/doesnt/exist/%s", basedirpath, testfile); assert (rc == -1); zconfig_destroy (&root); zchunk_destroy (&chunk); // Test subtree removal { zconfig_t *root = zconfig_str_load ( "context\n" " iothreads = 1\n" " verbose = 1 # Ask for a trace\n" "main\n" " type = zqueue # ZMQ_DEVICE type\n" " frontend\n" " option\n" " hwm = 1000\n" " swap = 25000000 # 25MB\n" " bind = 'inproc://addr1'\n" " bind = 'ipc://addr2'\n" " backend\n" " bind = inproc://addr3\n" ); zconfig_t *to_delete = zconfig_locate (root, "main/frontend"); assert (to_delete); zconfig_remove (to_delete); char *value = zconfig_get (root, "/main/type", NULL); assert (value); assert (streq (value, "zqueue")); value = zconfig_get (root, "/main/backend/bind", NULL); assert (value); assert (streq (value, "inproc://addr3")); value = zconfig_get (root, "/main/frontend", NULL); assert (value); value = zconfig_get (root, "/main/frontend/option", NULL); assert (value == NULL); value = zconfig_get (root, "/main/frontend/option/swap", NULL); assert (value == NULL); zconfig_destroy (&root); } // Test str_load zconfig_t *config = zconfig_str_load ( "malamute\n" " endpoint = ipc://@/malamute\n" " producer = STREAM\n" " consumer\n" " STREAM2 = .*\n" " STREAM3 = HAM\n" "server\n" " verbose = true\n" ); assert (config); assert (streq (zconfig_get (config, "malamute/endpoint", NULL), "ipc://@/malamute")); assert (streq (zconfig_get (config, "malamute/producer", NULL), "STREAM")); assert (zconfig_locate (config, "malamute/consumer")); zconfig_t *c = zconfig_child (zconfig_locate (config, "malamute/consumer")); assert (c); assert (streq (zconfig_name (c), "STREAM2")); assert (streq (zconfig_value (c), ".*")); c = zconfig_next (c); assert (c); assert (streq (zconfig_name (c), "STREAM3")); assert (streq (zconfig_value (c), "HAM")); c = zconfig_next (c); assert (!c); assert (streq (zconfig_get (config, "server/verbose", NULL), "true")); zconfig_destroy (&config); // Delete all test files dir = zdir_new (basedirpath, NULL); assert (dir); zdir_remove (dir, true); zdir_destroy (&dir); zstr_free (&basedirpath); zstr_free (&filepath); #if defined (__WINDOWS__) zsys_shutdown(); #endif // @end printf ("OK\n"); }
void zfile_test (bool verbose) { printf (" * zfile: "); // @selftest const char *SELFTEST_DIR_RW = "src/selftest-rw"; const char *testbasedir = "this"; const char *testsubdir = "is/a/test"; const char *testfile = "bilbo"; const char *testlink = "bilbo.ln"; char *basedirpath = NULL; // subdir in a test, under SELFTEST_DIR_RW char *dirpath = NULL; // subdir in a test, under basedirpath char *filepath = NULL; // pathname to testfile in a test, in dirpath char *linkpath = NULL; // pathname to testlink in a test, in dirpath basedirpath = zsys_sprintf ("%s/%s", SELFTEST_DIR_RW, testbasedir); assert (basedirpath); dirpath = zsys_sprintf ("%s/%s", basedirpath, testsubdir); assert (dirpath); filepath = zsys_sprintf ("%s/%s", dirpath, testfile); assert (filepath); linkpath = zsys_sprintf ("%s/%s", dirpath, testlink); assert (linkpath); // This subtest is specifically for NULL as current directory, so // no SELFTEST_DIR_RW here; testfile should have no slashes inside. // Normally tests clean up in zfile_destroy(), but if a selftest run // dies e.g. on assert(), workspace remains dirty. Better clean it up. if (zfile_exists (testfile) ) { if (verbose) zsys_debug ("zfile_test() has to remove ./%s that should not have been here", testfile); zfile_delete (testfile); } zfile_t *file = zfile_new (NULL, testfile); assert (file); assert (streq (zfile_filename (file, "."), testfile)); assert (zfile_is_readable (file) == false); zfile_destroy (&file); // Create a test file in some random subdirectory if (verbose) zsys_debug ("zfile_test() at timestamp %" PRIi64 ": " "Creating new zfile %s", zclock_time(), filepath ); if (zfile_exists (filepath) ) { if (verbose) zsys_debug ("zfile_test() has to remove %s that should not have been here", filepath); zfile_delete (filepath); } file = zfile_new (dirpath, testfile); assert (file); int rc = zfile_output (file); assert (rc == 0); zchunk_t *chunk = zchunk_new (NULL, 100); assert (chunk); zchunk_fill (chunk, 0, 100); // Write 100 bytes at position 1,000,000 in the file if (verbose) zsys_debug ("zfile_test() at timestamp %" PRIi64 ": " "Writing 100 bytes at position 1,000,000 in the file", zclock_time() ); rc = zfile_write (file, chunk, 1000000); if (verbose) zsys_debug ("zfile_test() at timestamp %" PRIi64 ": " "Wrote 100 bytes at position 1,000,000 in the file, result code %d", zclock_time(), rc ); assert (rc == 0); zchunk_destroy (&chunk); zfile_close (file); assert (zfile_is_readable (file)); assert (zfile_cursize (file) == 1000100); if (verbose) zsys_debug ("zfile_test() at timestamp %" PRIi64 ": " "Testing if file is NOT stable (is younger than 1 sec)", zclock_time() ); assert (!zfile_is_stable (file)); if (verbose) zsys_debug ("zfile_test() at timestamp %" PRIi64 ": " "Passed the lag-dependent tests", zclock_time() ); assert (zfile_digest (file)); // Now truncate file from outside int handle = open (filepath, O_WRONLY | O_TRUNC | O_BINARY, 0); assert (handle >= 0); rc = write (handle, "Hello, World\n", 13); assert (rc == 13); close (handle); assert (zfile_has_changed (file)); #ifdef CZMQ_BUILD_DRAFT_API zclock_sleep ((int)zsys_file_stable_age_msec() + 50); #else zclock_sleep (5050); #endif assert (zfile_has_changed (file)); assert (!zfile_is_stable (file)); zfile_restat (file); assert (zfile_is_stable (file)); assert (streq (zfile_digest (file), "4AB299C8AD6ED14F31923DD94F8B5F5CB89DFB54")); // Check we can read from file rc = zfile_input (file); assert (rc == 0); chunk = zfile_read (file, 1000100, 0); assert (chunk); assert (zchunk_size (chunk) == 13); zchunk_destroy (&chunk); zfile_close (file); // Check we can read lines from file rc = zfile_input (file); assert (rc == 0); const char *line = zfile_readln (file); assert (streq (line, "Hello, World")); line = zfile_readln (file); assert (line == NULL); zfile_close (file); // Try some fun with symbolic links zfile_t *link = zfile_new (dirpath, testlink); assert (link); rc = zfile_output (link); assert (rc == 0); fprintf (zfile_handle (link), "%s\n", filepath); zfile_destroy (&link); link = zfile_new (dirpath, testlink); assert (link); rc = zfile_input (link); assert (rc == 0); chunk = zfile_read (link, 1000100, 0); assert (chunk); assert (zchunk_size (chunk) == 13); zchunk_destroy (&chunk); zfile_destroy (&link); // Remove file and directory zdir_t *dir = zdir_new (basedirpath, NULL); assert (dir); assert (zdir_cursize (dir) == 26); zdir_remove (dir, true); assert (zdir_cursize (dir) == 0); zdir_destroy (&dir); // Check we can no longer read from file assert (zfile_is_readable (file)); zfile_restat (file); assert (!zfile_is_readable (file)); rc = zfile_input (file); assert (rc == -1); zfile_destroy (&file); // This set of tests is done, free the strings for reuse zstr_free (&basedirpath); zstr_free (&dirpath); zstr_free (&filepath); zstr_free (&linkpath); const char *eof_checkfile = "eof_checkfile"; filepath = zsys_sprintf ("%s/%s", SELFTEST_DIR_RW, eof_checkfile); assert (filepath); if (zfile_exists (filepath) ) { if (verbose) zsys_debug ("zfile_test() has to remove %s that should not have been here", filepath); zfile_delete (filepath); } zstr_free (&filepath); file = zfile_new (SELFTEST_DIR_RW, eof_checkfile); assert (file); // 1. Write something first rc = zfile_output (file); assert (rc == 0); chunk = zchunk_new ("123456789", 9); assert (chunk); rc = zfile_write (file, chunk, 0); assert (rc == 0); zchunk_destroy (&chunk); zfile_close (file); assert (zfile_cursize (file) == 9); // 2. Read the written something rc = zfile_input (file); assert (rc != -1); // try to read more bytes than there is in the file chunk = zfile_read (file, 1000, 0); assert (zfile_eof(file)); assert (zchunk_streq (chunk, "123456789")); zchunk_destroy (&chunk); // reading is ok chunk = zfile_read (file, 5, 0); assert (!zfile_eof(file)); assert (zchunk_streq (chunk, "12345")); zchunk_destroy (&chunk); // read from non zero offset until the end chunk = zfile_read (file, 5, 5); assert (zfile_eof(file)); assert (zchunk_streq (chunk, "6789")); zchunk_destroy (&chunk); zfile_remove (file); zfile_close (file); zfile_destroy (&file); #ifdef CZMQ_BUILD_DRAFT_API zfile_t *tempfile = zfile_tmp (); assert (tempfile); assert (zfile_filename (tempfile, NULL)); assert (zsys_file_exists (zfile_filename (tempfile, NULL))); zchunk_t *tchunk = zchunk_new ("HELLO", 6); assert (zfile_write (tempfile, tchunk, 0) == 0); zchunk_destroy (&tchunk); char *filename = strdup (zfile_filename (tempfile, NULL)); zfile_destroy (&tempfile); assert (!zsys_file_exists (filename)); zstr_free (&filename); #endif // CZMQ_BUILD_DRAFT_API #if defined (__WINDOWS__) zsys_shutdown(); #endif // @end printf ("OK\n"); }
int zauth_test (bool verbose) { printf (" * zauth: "); #if (ZMQ_VERSION_MAJOR == 4) // @selftest // Create temporary directory for test files # define TESTDIR ".test_zauth" zsys_dir_create (TESTDIR); // Install the authenticator zctx_t *ctx = zctx_new (); zauth_t *auth = zauth_new (ctx); assert (auth); zauth_set_verbose (auth, verbose); // A default NULL connection should always success, and not go through // our authentication infrastructure at all. void *server = zsocket_new (ctx, ZMQ_PUSH); void *client = zsocket_new (ctx, ZMQ_PULL); bool success = s_can_connect (server, client); assert (success); // When we set a domain on the server, we switch on authentication // for NULL sockets, but with no policies, the client connection will // be allowed. // // TODO: libzmq should accept new security options after unbind/bind // but for now we have to create a new server socket each time. server = zsocket_new (ctx, ZMQ_PUSH); zsocket_set_zap_domain (server, "global"); success = s_can_connect (server, client); assert (success); // Blacklist 127.0.0.1, connection should fail zauth_deny (auth, "127.0.0.1"); success = s_can_connect (server, client); assert (!success); // Whitelist our address, which overrides the blacklist zauth_allow (auth, "127.0.0.1"); success = s_can_connect (server, client); assert (success); // Try PLAIN authentication FILE *password = fopen (TESTDIR "/password-file", "w"); assert (password); fprintf (password, "admin=Password\n"); fclose (password); zsocket_set_plain_server (server, 1); zsocket_set_plain_username (client, "admin"); zsocket_set_plain_password (client, "Password"); success = s_can_connect (server, client); assert (!success); zauth_configure_plain (auth, "*", TESTDIR "/password-file"); success = s_can_connect (server, client); assert (success); zsocket_set_plain_password (client, "Bogus"); success = s_can_connect (server, client); assert (!success); # if defined (HAVE_LIBSODIUM) // Try CURVE authentication // We'll create two new certificates and save the client public // certificate on disk; in a real case we'd transfer this securely // from the client machine to the server machine. zcert_t *server_cert = zcert_new (); zcert_apply (server_cert, server); zsocket_set_curve_server (server, 1); zcert_t *client_cert = zcert_new (); zcert_apply (client_cert, client); char *server_key = zcert_public_txt (server_cert); zsocket_set_curve_serverkey (client, server_key); // We've not set-up any authentication, connection will fail success = s_can_connect (server, client); assert (!success); // PH: 2013/09/18 // There's an issue with libzmq where it sometimes fails to // connect even if the ZAP handler allows it. It's timing // dependent, so this is a voodoo hack. To be removed, I've // no idea this even applies to all boxes. sleep (1); // Test CURVE_ALLOW_ANY zauth_configure_curve (auth, "*", CURVE_ALLOW_ANY); success = s_can_connect (server, client); assert (success); // Test full client authentication using certificates zcert_save_public (client_cert, TESTDIR "/mycert.txt"); zauth_configure_curve (auth, "*", TESTDIR); success = s_can_connect (server, client); assert (success); zcert_destroy (&server_cert); zcert_destroy (&client_cert); # endif // Remove the authenticator and check a normal connection works zauth_destroy (&auth); success = s_can_connect (server, client); assert (success); zctx_destroy (&ctx); // Delete all test files zdir_t *dir = zdir_new (TESTDIR, NULL); zdir_remove (dir, true); zdir_destroy (&dir); // @end #endif printf ("OK\n"); return 0; }
JNIEXPORT void JNICALL Java_org_zeromq_czmq_Zdir__1_1destroy (JNIEnv *env, jclass c, jlong self) { zdir_destroy ((zdir_t **) &self); }
void zconfig_test (bool verbose) { printf (" * zconfig: "); // @selftest // Create temporary directory for test files # define TESTDIR ".test_zconfig" zsys_dir_create (TESTDIR); zconfig_t *root = zconfig_new ("root", NULL); assert (root); zconfig_t *section, *item; section = zconfig_new ("headers", root); assert (section); item = zconfig_new ("email", section); assert (item); zconfig_set_value (item, "*****@*****.**"); item = zconfig_new ("name", section); assert (item); zconfig_set_value (item, "Justin Kayce"); zconfig_putf (root, "/curve/secret-key", "%s", "Top Secret"); zconfig_set_comment (root, " CURVE certificate"); zconfig_set_comment (root, " -----------------"); assert (zconfig_comments (root)); zconfig_save (root, TESTDIR "/test.cfg"); zconfig_destroy (&root); root = zconfig_load (TESTDIR "/test.cfg"); if (verbose) zconfig_save (root, "-"); assert (streq (zconfig_filename (root), TESTDIR "/test.cfg")); char *email = zconfig_get (root, "/headers/email", NULL); assert (email); assert (streq (email, "*****@*****.**")); char *passwd = zconfig_get (root, "/curve/secret-key", NULL); assert (passwd); assert (streq (passwd, "Top Secret")); zconfig_savef (root, "%s/%s", TESTDIR, "test.cfg"); assert (!zconfig_has_changed (root)); int rc = zconfig_reload (&root); assert (rc == 0); assert (!zconfig_has_changed (root)); zconfig_destroy (&root); // Test chunk load/save root = zconfig_new ("root", NULL); assert (root); section = zconfig_new ("section", root); assert (section); item = zconfig_new ("value", section); assert (item); zconfig_set_value (item, "somevalue"); zconfig_t *search = zconfig_locate (root, "section/value"); assert (search == item); zchunk_t *chunk = zconfig_chunk_save (root); assert (strlen ((char *) zchunk_data (chunk)) == 32); char *string = zconfig_str_save (root); assert (string); assert (streq (string, (char *) zchunk_data (chunk))); free (string); assert (chunk); zconfig_destroy (&root); root = zconfig_chunk_load (chunk); assert (root); char *value = zconfig_get (root, "/section/value", NULL); assert (value); assert (streq (value, "somevalue")); // Test config can't be saved to a file in a path that doesn't // exist or isn't writable rc = zconfig_savef (root, "%s/path/that/doesnt/exist/%s", TESTDIR, "test.cfg"); assert (rc == -1); zconfig_destroy (&root); zchunk_destroy (&chunk); // Delete all test files zdir_t *dir = zdir_new (TESTDIR, NULL); assert (dir); zdir_remove (dir, true); zdir_destroy (&dir); // @end printf ("OK\n"); }
void zfile_test (bool verbose) { printf (" * zfile: "); // @selftest zfile_t *file = zfile_new (NULL, "bilbo"); assert (streq (zfile_filename (file, "."), "bilbo")); assert (zfile_is_readable (file) == false); zfile_destroy (&file); // Create a test file in some random subdirectory file = zfile_new ("./this/is/a/test", "bilbo"); int rc = zfile_output (file); assert (rc == 0); zchunk_t *chunk = zchunk_new (NULL, 100); zchunk_fill (chunk, 0, 100); // Write 100 bytes at position 1,000,000 in the file rc = zfile_write (file, chunk, 1000000); assert (rc == 0); zchunk_destroy (&chunk); zfile_close (file); assert (zfile_is_readable (file)); assert (zfile_cursize (file) == 1000100); assert (!zfile_is_stable (file)); // Now append one byte to file from outside int handle = open ("./this/is/a/test/bilbo", O_WRONLY | O_TRUNC | O_BINARY, 0); assert (handle >= 0); rc = write (handle, "Hello, World\n", 13); assert (rc == 13); close (handle); assert (zfile_has_changed (file)); zclock_sleep (1001); assert (zfile_has_changed (file)); assert (!zfile_is_stable (file)); zfile_restat (file); assert (zfile_is_stable (file)); assert (streq (zfile_digest (file), "4AB299C8AD6ED14F31923DD94F8B5F5CB89DFB54")); // Check we can read from file rc = zfile_input (file); assert (rc == 0); chunk = zfile_read (file, 1000100, 0); assert (chunk); assert (zchunk_size (chunk) == 13); zchunk_destroy (&chunk); zfile_close (file); // Try some fun with symbolic links zfile_t *link = zfile_new ("./this/is/a/test", "bilbo.ln"); rc = zfile_output (link); assert (rc == 0); fprintf (zfile_handle (link), "./this/is/a/test/bilbo\n"); zfile_destroy (&link); link = zfile_new ("./this/is/a/test", "bilbo.ln"); rc = zfile_input (link); assert (rc == 0); chunk = zfile_read (link, 1000100, 0); assert (chunk); assert (zchunk_size (chunk) == 13); zchunk_destroy (&chunk); zfile_destroy (&link); // Remove file and directory zdir_t *dir = zdir_new ("./this", NULL); assert (zdir_cursize (dir) == 26); zdir_remove (dir, true); assert (zdir_cursize (dir) == 0); zdir_destroy (&dir); // Check we can no longer read from file assert (zfile_is_readable (file)); zfile_restat (file); assert (!zfile_is_readable (file)); rc = zfile_input (file); assert (rc == -1); zfile_destroy (&file); // @end printf ("OK\n"); }
zdir_t * zdir_new (const char *path, const char *parent) { zdir_t *self = (zdir_t *) zmalloc (sizeof (zdir_t)); if (!self) return NULL; if (parent) { if (streq (parent, "-")) { self->trimmed = true; self->path = strdup (path); if (!self->path) { zdir_destroy (&self); return NULL; } } else { self->path = (char *) zmalloc (strlen (path) + strlen (parent) + 2); if (self->path) sprintf (self->path, "%s/%s", parent, path); else { zdir_destroy (&self); return NULL; } } } else { self->path = strdup (path); if (!self->path) { zdir_destroy (&self); return NULL; } } if (self->path) self->files = zlist_new (); if (self->files) self->subdirs = zlist_new (); if (!self->subdirs) { zdir_destroy (&self); return NULL; } #if (defined (WIN32)) // On Windows, replace backslashes by normal slashes char *path_clean_ptr = self->path; while (*path_clean_ptr) { if (*path_clean_ptr == '\\') *path_clean_ptr = '/'; path_clean_ptr++; } // Remove any trailing slash if (self->path [strlen (self->path) - 1] == '/') self->path [strlen (self->path) - 1] = 0; // Win32 wants a wildcard at the end of the path char *wildcard = (char *) zmalloc (strlen (self->path) + 3); if (!wildcard) { zdir_destroy (&self); return NULL; } sprintf (wildcard, "%s/*", self->path); WIN32_FIND_DATAA entry; HANDLE handle = FindFirstFileA (wildcard, &entry); free (wildcard); if (handle != INVALID_HANDLE_VALUE) { // We have read an entry, so return those values s_win32_populate_entry (self, &entry); while (FindNextFileA (handle, &entry)) s_win32_populate_entry (self, &entry); FindClose (handle); } #else // Remove any trailing slash if (self->path [strlen (self->path) - 1] == '/') self->path [strlen (self->path) - 1] = 0; DIR *handle = opendir (self->path); if (handle) { // Calculate system-specific size of dirent block int dirent_size = offsetof (struct dirent, d_name) + pathconf (self->path, _PC_NAME_MAX) + 1; struct dirent *entry = (struct dirent *) zmalloc (dirent_size); if (!entry) { zdir_destroy (&self); return NULL; } struct dirent *result; int rc = readdir_r (handle, entry, &result); while (rc == 0 && result != NULL) { s_posix_populate_entry (self, entry); rc = readdir_r (handle, entry, &result); } free (entry); closedir (handle); } #endif else {
void zcertstore_test (bool verbose) { printf (" * zcertstore: "); if (verbose) printf ("\n"); // @selftest const char *SELFTEST_DIR_RW = "src/selftest-rw"; const char *testbasedir = ".test_zcertstore"; const char *testfile = "mycert.txt"; char *basedirpath = NULL; // subdir in a test, under SELFTEST_DIR_RW char *filepath = NULL; // pathname to testfile in a test, in dirpath basedirpath = zsys_sprintf ("%s/%s", SELFTEST_DIR_RW, testbasedir); assert (basedirpath); filepath = zsys_sprintf ("%s/%s", basedirpath, testfile); assert (filepath); // Make sure old aborted tests do not hinder us zdir_t *dir = zdir_new (basedirpath, NULL); if (dir) { zdir_remove (dir, true); zdir_destroy (&dir); } zsys_file_delete (filepath); zsys_dir_delete (basedirpath); // Create temporary directory for test files zsys_dir_create (basedirpath); // Load certificate store from disk; it will be empty zcertstore_t *certstore = zcertstore_new (basedirpath); assert (certstore); // Create a single new certificate and save to disk zcert_t *cert = zcert_new (); assert (cert); char *client_key = strdup (zcert_public_txt (cert)); assert (client_key); zcert_set_meta (cert, "name", "John Doe"); zcert_save (cert, filepath); zcert_destroy (&cert); // Check that certificate store refreshes as expected cert = zcertstore_lookup (certstore, client_key); assert (cert); assert (streq (zcert_meta (cert, "name"), "John Doe")); #ifdef CZMQ_BUILD_DRAFT_API // DRAFT-API: Security // Iterate through certs zlistx_t *certs = zcertstore_certs(certstore); cert = (zcert_t *) zlistx_first(certs); int cert_count = 0; while (cert) { assert (streq (zcert_meta (cert, "name"), "John Doe")); cert = (zcert_t *) zlistx_next(certs); cert_count++; } assert(cert_count==1); zlistx_destroy(&certs); #endif // Test custom loader test_loader_state *state = (test_loader_state *) zmalloc (sizeof (test_loader_state)); state->index = 0; zcertstore_set_loader (certstore, s_test_loader, s_test_destructor, (void *)state); #if (ZMQ_VERSION_MAJOR >= 4) cert = zcertstore_lookup (certstore, client_key); assert (cert == NULL); cert = zcertstore_lookup (certstore, "abcdefghijklmnopqrstuvwxyzabcdefghijklmn"); assert (cert); #endif freen (client_key); if (verbose) zcertstore_print (certstore); zcertstore_destroy (&certstore); // Delete all test files dir = zdir_new (basedirpath, NULL); assert (dir); zdir_remove (dir, true); zdir_destroy (&dir); zstr_free (&basedirpath); zstr_free (&filepath); #if defined (__WINDOWS__) zsys_shutdown(); #endif // @end printf ("OK\n"); }
void curve_client_test (bool verbose) { printf (" * curve_client: "); // @selftest // Create temporary directory for test files zsys_dir_create (TESTDIR); // We'll create two new certificates and save the client public // certificate on disk; in a real case we'd transfer this securely // from the client machine to the server machine. zcert_t *server_cert = zcert_new (); zcert_save (server_cert, TESTDIR "/server.cert"); // We'll run the server as a background task, and the // client in this foreground thread. zthread_new (server_task, &verbose); zcert_t *client_cert = zcert_new (); zcert_save_public (client_cert, TESTDIR "/client.cert"); curve_client_t *client = curve_client_new (&client_cert); curve_client_set_metadata (client, "Client", "CURVEZMQ/curve_client"); curve_client_set_metadata (client, "Identity", "E475DA11"); curve_client_set_verbose (client, verbose); curve_client_connect (client, "tcp://127.0.0.1:9005", (byte *)zcert_public_key (server_cert)); curve_client_sendstr (client, "Hello, World"); char *reply = curve_client_recvstr (client); assert (streq (reply, "Hello, World")); free (reply); // Try a multipart message zmsg_t *msg = zmsg_new (); zmsg_addstr (msg, "Hello, World"); zmsg_addstr (msg, "Second frame"); curve_client_send (client, &msg); msg = curve_client_recv (client); assert (zmsg_size (msg) == 2); zmsg_destroy (&msg); // Now send messages of increasing size, check they work int count; int size = 0; for (count = 0; count < 18; count++) { if (verbose) printf ("Testing message of size=%d...\n", size); zframe_t *data = zframe_new (NULL, size); int byte_nbr; // Set data to sequence 0...255 repeated for (byte_nbr = 0; byte_nbr < size; byte_nbr++) zframe_data (data)[byte_nbr] = (byte) byte_nbr; msg = zmsg_new (); zmsg_prepend (msg, &data); curve_client_send (client, &msg); msg = curve_client_recv (client); data = zmsg_pop (msg); assert (data); assert (zframe_size (data) == size); for (byte_nbr = 0; byte_nbr < size; byte_nbr++) { assert (zframe_data (data)[byte_nbr] == (byte) byte_nbr); } zframe_destroy (&data); zmsg_destroy (&msg); size = size * 2 + 1; } // Signal end of test curve_client_sendstr (client, "END"); reply = curve_client_recvstr (client); free (reply); zcert_destroy (&server_cert); zcert_destroy (&client_cert); curve_client_destroy (&client); // Delete all test files zdir_t *dir = zdir_new (TESTDIR, NULL); zdir_remove (dir, true); zdir_destroy (&dir); // @end // Ensure server thread has exited before we do zclock_sleep (100); printf ("OK\n"); }
void zauth_test (bool verbose) { printf (" * zauth: "); #if (ZMQ_VERSION_MAJOR == 4) if (verbose) printf ("\n"); // @selftest // Create temporary directory for test files # define TESTDIR ".test_zauth" zsys_dir_create (TESTDIR); // Check there's no authentication zsock_t *server = zsock_new (ZMQ_PUSH); assert (server); zsock_t *client = zsock_new (ZMQ_PULL); assert (client); bool success = s_can_connect (&server, &client); assert (success); // Install the authenticator zactor_t *auth = zactor_new (zauth, NULL); assert (auth); if (verbose) { zstr_sendx (auth, "VERBOSE", NULL); zsock_wait (auth); } // Check there's no authentication on a default NULL server success = s_can_connect (&server, &client); assert (success); // When we set a domain on the server, we switch on authentication // for NULL sockets, but with no policies, the client connection // will be allowed. zsock_set_zap_domain (server, "global"); success = s_can_connect (&server, &client); assert (success); // Blacklist 127.0.0.1, connection should fail zsock_set_zap_domain (server, "global"); zstr_sendx (auth, "DENY", "127.0.0.1", NULL); zsock_wait (auth); success = s_can_connect (&server, &client); assert (!success); // Whitelist our address, which overrides the blacklist zsock_set_zap_domain (server, "global"); zstr_sendx (auth, "ALLOW", "127.0.0.1", NULL); zsock_wait (auth); success = s_can_connect (&server, &client); assert (success); // Try PLAIN authentication zsock_set_plain_server (server, 1); zsock_set_plain_username (client, "admin"); zsock_set_plain_password (client, "Password"); success = s_can_connect (&server, &client); assert (!success); FILE *password = fopen (TESTDIR "/password-file", "w"); assert (password); fprintf (password, "admin=Password\n"); fclose (password); zsock_set_plain_server (server, 1); zsock_set_plain_username (client, "admin"); zsock_set_plain_password (client, "Password"); zstr_sendx (auth, "PLAIN", TESTDIR "/password-file", NULL); zsock_wait (auth); success = s_can_connect (&server, &client); assert (success); zsock_set_plain_server (server, 1); zsock_set_plain_username (client, "admin"); zsock_set_plain_password (client, "Bogus"); success = s_can_connect (&server, &client); assert (!success); if (zsys_has_curve ()) { // Try CURVE authentication // We'll create two new certificates and save the client public // certificate on disk; in a real case we'd transfer this securely // from the client machine to the server machine. zcert_t *server_cert = zcert_new (); assert (server_cert); zcert_t *client_cert = zcert_new (); assert (client_cert); char *server_key = zcert_public_txt (server_cert); // Test without setting-up any authentication zcert_apply (server_cert, server); zcert_apply (client_cert, client); zsock_set_curve_server (server, 1); zsock_set_curve_serverkey (client, server_key); success = s_can_connect (&server, &client); assert (!success); // Test CURVE_ALLOW_ANY zcert_apply (server_cert, server); zcert_apply (client_cert, client); zsock_set_curve_server (server, 1); zsock_set_curve_serverkey (client, server_key); zstr_sendx (auth, "CURVE", CURVE_ALLOW_ANY, NULL); zsock_wait (auth); success = s_can_connect (&server, &client); assert (success); // Test full client authentication using certificates zcert_apply (server_cert, server); zcert_apply (client_cert, client); zsock_set_curve_server (server, 1); zsock_set_curve_serverkey (client, server_key); zcert_save_public (client_cert, TESTDIR "/mycert.txt"); zstr_sendx (auth, "CURVE", TESTDIR, NULL); zsock_wait (auth); success = s_can_connect (&server, &client); assert (success); zcert_destroy (&server_cert); zcert_destroy (&client_cert); } // Remove the authenticator and check a normal connection works zactor_destroy (&auth); success = s_can_connect (&server, &client); assert (success); zsock_destroy (&client); zsock_destroy (&server); // Delete all test files zdir_t *dir = zdir_new (TESTDIR, NULL); assert (dir); zdir_remove (dir, true); zdir_destroy (&dir); // @end #endif printf ("OK\n"); }
void curve_server_test (bool verbose) { printf (" * curve_server: "); // @selftest // Create temporary directory for test files srand (time (NULL)); zsys_dir_create (TESTDIR); zcert_t *server_cert = zcert_new (); zcert_save (server_cert, TESTDIR "/server.cert"); // Install the authenticator zctx_t *ctx = zctx_new (); zauth_t *auth = zauth_new (ctx); assert (auth); zauth_set_verbose (auth, verbose); zauth_configure_curve (auth, "*", TESTDIR); // We'll run a set of clients as background tasks, and the // server in this foreground thread. Don't pass verbose to // the clients as the results are unreadable. int live_clients; for (live_clients = 0; live_clients < 5; live_clients++) zthread_new (client_task, &verbose); curve_server_t *server = curve_server_new (ctx, &server_cert); curve_server_set_verbose (server, verbose); curve_server_bind (server, "tcp://127.0.0.1:9006"); while (live_clients > 0) { zmsg_t *msg = curve_server_recv (server); if (memcmp (zframe_data (zmsg_last (msg)), "END", 3) == 0) live_clients--; curve_server_send (server, &msg); } // Try an invalid client/server combination byte bad_server_key [32] = { 0 }; zcert_t *unknown = zcert_new (); curve_client_t *client = curve_client_new (&unknown); curve_client_set_verbose (client, true); curve_client_connect (client, "tcp://127.0.0.1:9006", bad_server_key); curve_client_sendstr (client, "Hello, World"); // Expect no reply after 250msec zmq_pollitem_t pollitems [] = { { curve_client_handle (client), 0, ZMQ_POLLIN, 0 } }; assert (zmq_poll (pollitems, 1, 250) == 0); curve_client_destroy (&client); // Delete all test files zdir_t *dir = zdir_new (TESTDIR, NULL); zdir_remove (dir, true); zdir_destroy (&dir); curve_server_destroy (&server); zauth_destroy (&auth); zctx_destroy (&ctx); // @end // Ensure client threads have exited before we do zclock_sleep (100); printf ("OK\n"); }