int zcert_save (zcert_t *self, char *format, ...) { assert (self); assert (format); va_list argptr; va_start (argptr, format); char *filename = zsys_vprintf (format, argptr); va_end (argptr); // Save public certificate using specified filename zcert_save_public (self, filename); // Now save secret certificate using filename with "_secret" suffix s_save_metadata_all (self); zconfig_comment (self->config, " ZeroMQ CURVE **Secret** Certificate"); zconfig_comment (self->config, " DO NOT PROVIDE THIS FILE TO OTHER USERS nor change its permissions."); zconfig_put (self->config, "/curve/public-key", self->public_txt); zconfig_put (self->config, "/curve/secret-key", self->secret_txt); char filename_secret [256]; snprintf (filename_secret, 256, "%s_secret", filename); zsys_file_mode_private (); int rc = zconfig_save (self->config, filename_secret); zsys_file_mode_default (); zstr_free (&filename); return rc; }
void zconfig_put (zconfig_t *self, char *path, char *value) { if (*path == '/') path++; // Check length of next path segment char *slash = strchr (path, '/'); int length = strlen (path); if (slash) length = slash - path; // Find or create items starting at first child of root zconfig_t *child = self->child; while (child) { if (strlen (child->name) == length && memcmp (child->name, path, length) == 0) { // This segment exists if (slash) // Recurse to next level zconfig_put (child, slash + 1, value); else zconfig_set_value (child, "%s", value); return; } child = child->next; } // This segment doesn't exist, create it child = zconfig_new (path, self); child->name [length] = 0; if (slash) // Recurse down further zconfig_put (child, slash, value); else zconfig_set_value (child, "%s", value); }
// Process message from pipe static void server_control_message (server_t *self) { zmsg_t *msg = zmsg_recv (self->pipe); char *method = zmsg_popstr (msg); if (streq (method, "BIND")) { char *endpoint = zmsg_popstr (msg); self->port = zsocket_bind (self->router, endpoint); zstr_sendf (self->pipe, "%d", self->port); free (endpoint); } else if (streq (method, "PUBLISH")) { char *location = zmsg_popstr (msg); char *alias = zmsg_popstr (msg); mount_t *mount = mount_new (location, alias); zlist_append (self->mounts, mount); free (location); free (alias); } else if (streq (method, "SET ANONYMOUS")) { char *enabled_string = zmsg_popstr (msg); long enabled = atoi (enabled_string); free (enabled_string); // Enable anonymous access without a config file zconfig_put (self->config, "security/anonymous", enabled? "1" :"0"); } else if (streq (method, "CONFIG")) { char *config_file = zmsg_popstr (msg); zconfig_destroy (&self->config); self->config = zconfig_load (config_file); if (self->config) server_apply_config (self); else { printf ("E: cannot load config file '%s'\n", config_file); self->config = zconfig_new ("root", NULL); } free (config_file); } else if (streq (method, "SETOPTION")) { char *path = zmsg_popstr (msg); char *value = zmsg_popstr (msg); zconfig_put (self->config, path, value); server_config_self (self); free (path); free (value); } else if (streq (method, "STOP")) { zstr_send (self->pipe, "OK"); self->stopped = true; } free (method); zmsg_destroy (&msg); }
// Apply configuration tree: // * apply server configuration // * print any echo items in top-level sections // * apply sections that match methods static void server_apply_config (server_t *self) { // Apply echo commands and class methods zconfig_t *section = zconfig_child (self->config); while (section) { zconfig_t *entry = zconfig_child (section); while (entry) { if (streq (zconfig_name (entry), "echo")) zclock_log (zconfig_value (entry)); entry = zconfig_next (entry); } if (streq (zconfig_name (section), "bind")) { char *endpoint = zconfig_resolve (section, "endpoint", "?"); self->port = zsocket_bind (self->router, endpoint); } else if (streq (zconfig_name (section), "publish")) { char *location = zconfig_resolve (section, "location", "?"); char *alias = zconfig_resolve (section, "alias", "?"); mount_t *mount = mount_new (location, alias); zlist_append (self->mounts, mount); } else if (streq (zconfig_name (section), "set_anonymous")) { long enabled = atoi (zconfig_resolve (section, "enabled", "")); // Enable anonymous access without a config file zconfig_put (self->config, "security/anonymous", enabled? "1" :"0"); } section = zconfig_next (section); } server_config_self (self); }
int hydra_post_save (hydra_post_t *self, const char *filename) { assert (self); assert (filename); // Creeate subdirectories if necessary zsys_dir_create ("posts"); zsys_dir_create ("posts/blobs"); // If post content hasn't yet been serialised, write it to disk in the // blobs directory and set the location property to point to it. if (self->content) { assert (!self->location); self->location = zsys_sprintf ("posts/blobs/%s", self->digest); FILE *output = fopen (self->location, "wb"); zchunk_write (self->content, output); zchunk_destroy (&self->content); fclose (output); } zconfig_t *root = zconfig_new ("root", NULL); zconfig_put (root, "/post/ident", hydra_post_ident (self)); zconfig_put (root, "/post/subject", self->subject); zconfig_put (root, "/post/timestamp", self->timestamp); zconfig_put (root, "/post/parent-id", self->parent_id); zconfig_put (root, "/post/mime-type", self->mime_type); zconfig_put (root, "/post/digest", self->digest); zconfig_put (root, "/post/location", self->location); zconfig_putf (root, "/post/content-size", "%ld", self->content_size); zconfig_savef (root, "posts/%s", filename); zconfig_destroy (&root); return 0; }
JNIEXPORT void JNICALL Java_zconfig__1_1put (JNIEnv *env, jclass c, jlong self, jstring path, jstring value) { char *path_ = (char *) (*env)->GetStringUTFChars (env, path, NULL); char *value_ = (char *) (*env)->GetStringUTFChars (env, value, NULL); zconfig_put ((zconfig_t *) self, path_, value_); (*env)->ReleaseStringUTFChars (env, path, path_); (*env)->ReleaseStringUTFChars (env, value, value_); }
int zcert_save_secret (zcert_t *self, const char *filename) { assert (self); assert (filename); s_save_metadata_all (self); zconfig_set_comment (self->config, " ZeroMQ CURVE **Secret** Certificate"); zconfig_set_comment (self->config, " DO NOT PROVIDE THIS FILE TO OTHER USERS nor change its permissions."); zconfig_put (self->config, "/curve/public-key", self->public_txt); zconfig_put (self->config, "/curve/secret-key", self->secret_txt); zsys_file_mode_private (); int rc = zconfig_save (self->config, filename); zsys_file_mode_default (); return rc; }
void zconfig_putf (zconfig_t *self, const char *path, const char *format, ...) { assert (self); va_list argptr; va_start (argptr, format); char *value = zsys_vprintf (format, argptr); va_end (argptr); zconfig_put (self, path, value); zstr_free (&value); }
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"); }
int zcert_save_public (zcert_t *self, const char *filename) { assert (self); assert (filename); s_save_metadata_all (self); zconfig_set_comment (self->config, " ZeroMQ CURVE Public Certificate"); zconfig_set_comment (self->config, " Exchange securely, or use a secure mechanism to verify the contents"); zconfig_set_comment (self->config, " of this file after exchange. Store public certificates in your home"); zconfig_set_comment (self->config, " directory, in the .curve subdirectory."); zconfig_put (self->config, "/curve/public-key", self->public_txt); int rc = zconfig_save (self->config, filename); return rc; }
int zcert_save_public (zcert_t *self, char *format, ...) { assert (self); assert (format); va_list argptr; va_start (argptr, format); char *filename = zsys_vprintf (format, argptr); va_end (argptr); s_save_metadata_all (self); zconfig_comment (self->config, " ZeroMQ CURVE Public Certificate"); zconfig_comment (self->config, " Exchange securely, or use a secure mechanism to verify the contents"); zconfig_comment (self->config, " of this file after exchange. Store public certificates in your home"); zconfig_comment (self->config, " directory, in the .curve subdirectory."); zconfig_put (self->config, "/curve/public-key", self->public_txt); int rc = zconfig_save (self->config, filename); zstr_free (&filename); return rc; }
/// // Insert or update configuration key with value void QmlZconfig::put (const QString &path, const QString &value) { zconfig_put (self, path.toUtf8().data(), value.toUtf8().data()); };
int main (int argc, char *argv []) { puts (PRODUCT); puts (COPYRIGHT); puts (NOWARRANTY); int argn = 1; bool verbose = false; if (argn < argc && streq (argv [argn], "-h")) { puts ("syntax: hydrad [ directory ]"); puts (" -- defaults to .hydra in current directory"); exit (0); } if (argn < argc && streq (argv [argn], "-v")) { verbose = true; argn++; } // By default, current node runs in .hydra directory; create this if // it's missing (don't create directory passed as argument); char *workdir = ".hydra"; if (argn < argc) workdir = argv [argn++]; else zsys_dir_create (workdir); // ---------------------------------------------------------------------- // This code eventually goes into a reusable hydra actor class // Switch to working directory zsys_info ("hydrad: data store in %s directory", workdir); if (zsys_dir_change (workdir)) { zsys_error ("hydrad: cannot access %s: %s", workdir, strerror (errno)); return 1; } // Check we are the only process currently running here if (zsys_run_as ("hydrad.lock", NULL, NULL)) { zsys_error ("hydrad: cannot start process safely, exiting"); return 1; } // Get node identity from config file, or generate new identity zconfig_t *config = zconfig_load ("hydra.cfg"); if (!config) { // Set defaults for Hydra service config = zconfig_new ("root", NULL); zconfig_put (config, "/server/timeout", "5000"); zconfig_put (config, "/server/background", "0"); zconfig_put (config, "/server/verbose", "0"); } char *identity = zconfig_resolve (config, "/hydra/identity", NULL); if (!identity) { zuuid_t *uuid = zuuid_new (); zconfig_put (config, "/hydra/identity", zuuid_str (uuid)); zconfig_put (config, "/hydra/nickname", "Anonymous"); zconfig_save (config, "hydra.cfg"); zuuid_destroy (&uuid); } // Create store structure, if necessary zsys_dir_create ("content"); zsys_dir_create ("posts"); // Start server and bind to ephemeral TCP port. We can run many // servers on the same box, for testing. zactor_t *server = zactor_new (hydra_server, NULL); if (verbose) zstr_send (server, "VERBOSE"); // Bind Hydra service to ephemeral port and get that port number char *command; int port_nbr; zsock_send (server, "ss", "CONFIGURE", "hydra.cfg"); zsock_send (server, "ss", "BIND", "tcp://*:*"); zsock_send (server, "s", "PORT"); zsock_recv (server, "si", &command, &port_nbr); zsys_info ("hydrad: TCP server started on port=%d", port_nbr); assert (streq (command, "PORT")); free (command); // We're going to use Zyre for discovery and presence, and our own // Hydra protocol for content exchange zyre_t *zyre = zyre_new (NULL); if (verbose) zyre_set_verbose (zyre); char *hostname = zsys_hostname (); char *endpoint = zsys_sprintf ("tcp://%s:%d", hostname, port_nbr); zyre_set_header (zyre, "X-HYDRA", "%s", endpoint); zstr_free (&endpoint); zstr_free (&hostname); if (zyre_start (zyre)) { zsys_info ("hydrad: can't start Zyre discovery service"); zactor_destroy (&server); zyre_destroy (&zyre); return 1; } // When we get a new peer, handle it zpoller_t *poller = zpoller_new (zyre_socket (zyre), NULL); while (!zpoller_terminated (poller)) { void *which = zpoller_wait (poller, -1); if (which == zyre_socket (zyre)) { zyre_event_t *event = zyre_event_new (zyre); if (zyre_event_type (event) == ZYRE_EVENT_ENTER) { zsys_debug ("hydrad: new peer name=%s endpoint=%s", zyre_event_name (event), zyre_event_header (event, "X-HYDRA")); s_handle_peer (zyre_event_header (event, "X-HYDRA"), verbose); } zyre_event_destroy (&event); } else break; } zsys_info ("hydrad: shutting down..."); zpoller_destroy (&poller); // Shutdown all services zactor_destroy (&server); zyre_destroy (&zyre); zconfig_destroy (&config); return 0; }
int main (int argc, char *argv []) { puts (PRODUCT); puts (COPYRIGHT); puts (NOWARRANTY); int argn = 1; bool verbose = false; bool force_foreground = false; if (argc > argn && streq (argv [argn], "-v")) { verbose = true; argn++; } if (argc > argn && streq (argv [argn], "-f")) { force_foreground = true; argn++; } if (argc > argn && streq (argv [argn], "-h")) { puts ("Usage: malamute [ -v ] [ -f ] [ -h | config-file ]"); puts (" Default config-file is 'malamute.cfg'"); return 0; } // Collect configuration file name const char *config_file = "malamute.cfg"; if (argc > argn) { config_file = argv [argn]; argn++; } zsys_init (); // Keep old behavior unless specified otherwise. if (!getenv ("ZSYS_LOGSYSTEM")) { zsys_set_logsystem(true); } zsys_set_pipehwm (0); zsys_set_sndhwm (0); zsys_set_rcvhwm (0); // Load config file for our own use here zsys_info ("loading configuration from '%s'...", config_file); zconfig_t *config = zconfig_load (config_file); if (!config) { zsys_info ("'%s' is missing, creating with defaults:", config_file); config = zconfig_new ("root", NULL); zconfig_put (config, "server/timeout", "5000"); zconfig_put (config, "server/background", "0"); zconfig_put (config, "server/workdir", "."); zconfig_put (config, "server/verbose", "0"); zconfig_put (config, "mlm_server/security/mechanism", "null"); zconfig_put (config, "mlm_server/bind/endpoint", MLM_DEFAULT_ENDPOINT); zconfig_print (config); zconfig_save (config, config_file); } // Do we want to run broker in the background? int as_daemon = !force_foreground && atoi (zconfig_resolve (config, "server/background", "0")); const char *workdir = zconfig_resolve (config, "server/workdir", "."); if (as_daemon) { zsys_info ("switching Malamute to background..."); if (zsys_daemonize (workdir)) return -1; } // Switch to user/group to run process under, if any if (zsys_run_as ( zconfig_resolve (config, "server/lockfile", NULL), zconfig_resolve (config, "server/group", NULL), zconfig_resolve (config, "server/user", NULL))) return -1; // Install authenticator (NULL or PLAIN) zactor_t *auth = zactor_new (zauth, NULL); assert (auth); if (verbose || atoi (zconfig_resolve (config, "server/auth/verbose", "0"))) { zstr_sendx (auth, "VERBOSE", NULL); zsock_wait (auth); } // Do PLAIN password authentication if requested const char *passwords = zconfig_resolve (config, "server/auth/plain", NULL); if (passwords) { zstr_sendx (auth, "PLAIN", passwords, NULL); zsock_wait (auth); } // Start Malamute server instance zactor_t *server = zactor_new (mlm_server, "Malamute"); if (verbose) zstr_send (server, "VERBOSE"); zstr_sendx (server, "LOAD", config_file, NULL); // Accept and print any message back from server while (true) { char *message = zstr_recv (server); if (message) { puts (message); free (message); } else { puts ("interrupted"); break; } } // Shutdown all services zactor_destroy (&server); zactor_destroy (&auth); // Destroy config tree zconfig_destroy (&config); #if defined (__WINDOWS__) zsys_shutdown (); #endif return 0; }