Commit bad06a81 authored by Alexander Withers's avatar Alexander Withers
Browse files

new gateway binary, removed cabana key

parent 4ec19b5d
all: server client
CFLAGS=--std=c99 -Wall -Wextra $(shell pkg-config --cflags libczmq)
LOADLIBES=$(shell pkg-config --libs libczmq)
server: server.o server_cmd.o keygen_cmd.o zsimpledisco.o
client: client.o zsimpledisco.o
server.static:
cc -o server server.c server_cmd.c zsimpledisco.c -static-libstdc++ -static -static-libgcc -Wall -Wextra -DCZMQ_BUILD_DRAFT_API=1 -DZMQ_BUILD_DRAFT_API=1 $(shell pkg-config --cflags --libs libczmq) -l pthread -lstdc++ -lm
all: gateway
CFLAGS=-Wall -Wextra $(shell pkg-config --cflags libzyre)
LOADLIBES= $(shell pkg-config --libs libzyre)
gateway: main.o keygen_cmd.o server_cmd.o gateway.o zsimpledisco.o
gateway.static: main.c gateway.c server_cmd.c zsimpledisco.c keygen_cmd.c
cc main.c gateway.c keygen_cmd.c server_cmd.c zsimpledisco.c -o gateway -static-libstdc++ -static -static-libgcc -Wall -Wextra $(shell pkg-config --cflags --libs libzyre) -lpthread -lstdc++ -lm
@echo OK!
#include "czmq_library.h"
#include "zsimpledisco.h"
int main(int argn, char *argv[])
{
if(argn < 2) {
fprintf(stderr, "Usage: %s tcp://127.0.0.1:9999 tcp://127.0.0.1:9998|key\n", argv[0]);
exit(1);
}
zsimpledisco_t *disco = zsimpledisco_new();
zsimpledisco_verbose(disco);
const char *private_key_path = getenv("PRIVATE_KEY_PATH");
if(private_key_path) {
zsimpledisco_set_private_key_path(disco, private_key_path);
}
for(int n=1;n<argn;n++) {
zsimpledisco_connect(disco, argv[n]);
}
char *key_str = zsys_sprintf ("Client-%d", getpid());
if(!getenv("QUIET"))
zsimpledisco_publish(disco, key_str, "Hello");
zpoller_t *poller = zpoller_new (NULL);
zpoller_add(poller, zsimpledisco_socket(disco));
zsimpledisco_get_values(disco);
while(1) {
zsock_t *which = zpoller_wait (poller, 1000);
if (which == zsimpledisco_socket (disco)) {
zmsg_t *msg = zmsg_recv (which);
char *key = zmsg_popstr (msg);
char *value = zmsg_popstr (msg);
printf("KEY VALUE PAIR: '%s' '%s'\n", key, value);
free (key);
free (value);
zmsg_destroy (&msg);
}
}
zsimpledisco_destroy(&disco);
}
No preview for this file type
// --------------------------------------------------------------------------
// Example Zyre distributed chat application
//
// Copyright (c) 2010-2014 The Authors
//
// 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.
// --------------------------------------------------------------------------
#include "zyre.h"
#include "zsimpledisco.h"
const char *getenv_with_default(const char *key, const char *def)
{
const char *val = getenv(key);
return val ? val : def;
}
void
bootstrap_simpledisco(zsimpledisco_t *disco, zcertstore_t *certstore)
{
zlistx_t *certs = zcertstore_certs(certstore);
zcert_t *cert = (zcert_t *) zlistx_first(certs);
int cert_count = 0;
int endpoint_count = 0;
while (cert) {
const char *endpoint = zcert_meta (cert, "simpledisco-endpoint");
const char *public_key = zcert_public_txt(cert);
if(endpoint) {
char *real_endpoint = zsys_sprintf("%s|%s", endpoint, public_key);
zsys_info("gateway: Connecting to simpledisco server @ %s using %s", endpoint, public_key);
zsimpledisco_connect(disco, real_endpoint);
zstr_free(&real_endpoint);
endpoint_count++;
}
cert = (zcert_t *) zlistx_next(certs);
cert_count++;
}
if(cert_count==0)
zsys_error("gateway: No certs found in certstore");
else if(endpoint_count==0)
zsys_error("gateway: No certs found in certstore that contain simpledisco-endpoint metadata");
zlistx_destroy(&certs);
}
void
maybe_create_untrusted_key(
zcertstore_t *certstore, zcertstore_t *certstore_untrusted,
const char *trusted_path, const char *untrusted_path,
const char *public_key)
{
zcert_t *cert;
cert = zcertstore_lookup(certstore, public_key);
if(cert)
return;
cert = zcertstore_lookup(certstore_untrusted, public_key);
if(cert)
return;
int file_num;
char *trusted_filename;
char *untrusted_filename;
for(file_num = 1 ; file_num < 1000 ; file_num++){
trusted_filename = zsys_sprintf("%s/discovered_%03d.key", trusted_path, file_num);
untrusted_filename = zsys_sprintf("%s/discovered_%03d.key", untrusted_path, file_num);
if (!zsys_file_exists(trusted_filename) && !zsys_file_exists(untrusted_filename))
break;
zstr_free(&trusted_filename);
zstr_free(&untrusted_filename);
}
assert(untrusted_filename);
zsys_debug("gateway: Discovered public_key: %s, adding to %s", public_key, untrusted_filename);
cert = zcert_new_from_txt(public_key, "");
zcert_save_public(cert, untrusted_filename);
zstr_free(&trusted_filename);
zstr_free(&untrusted_filename);
}
static void
gateway_actor (zsock_t *pipe, void *args)
{
int64_t last_bootstrap = 0;
const char *endpoint = getenv_with_default(
"ZYRE_BIND", "tcp://*:5670");
const char *pubsub_endpoint = getenv_with_default(
"PUBSUB_ENDPOINT", "tcp://127.0.0.1:14000");
const char *control_endpoint = getenv_with_default(
"CONTROL_ENDPOINT", "tcp://127.0.0.1:14001");
const char *private_key_path = getenv_with_default(
"PRIVATE_KEY_PATH", "client.key_secret");
const char *public_key_dir_path = getenv_with_default(
"PUBLIC_KEY_DIR_PATH", "./public_keys");
const char *untrusted_public_key_dir_path = getenv_with_default(
"UNTRUSTED_PUBLIC_KEY_DIR_PATH", "./public_keys_untrusted");
assert(!zsys_dir_create(public_key_dir_path));
assert(!zsys_dir_create(untrusted_public_key_dir_path));
zcertstore_t *certstore = zcertstore_new(public_key_dir_path);
assert(certstore);
zcertstore_t *certstore_untrusted = zcertstore_new(untrusted_public_key_dir_path);
assert(certstore_untrusted);
zsock_t *pub = zsock_new(ZMQ_PUB);
zsock_t *control = zsock_new(ZMQ_ROUTER);
if (-1 == zsock_bind(pub, "%s", pubsub_endpoint)) {
fprintf(stderr, "Faild to bind to PUBSUB_ENDPOINT %s", pubsub_endpoint);
perror(" ");
exit(1);
}
if (-1 == zsock_bind(control, "%s", control_endpoint)) {
fprintf(stderr, "Faild to bind to CONTROL_ENDPOINT %s", control_endpoint);
perror(" ");
exit(1);
}
zsimpledisco_t *disco = zsimpledisco_new();
zsimpledisco_verbose(disco);
zcert_t *cert = NULL;
if(private_key_path) {
zsimpledisco_set_private_key_path(disco, private_key_path);
cert = zcert_load(private_key_path);
zactor_t *auth = zactor_new (zauth,NULL);
zstr_send(auth,"VERBOSE");
zsock_wait(auth);
zstr_sendx (auth, "CURVE", public_key_dir_path, NULL);
zsock_wait(auth);
}
zyre_t *node = zyre_new ((char *) args);
if (!node)
return; // Could not create new node
//FIXME: The order of the next few lines matters a lot for some reason
//I should be able to start the node after the setup, but that isn't working
//because self->inbox gets hosed somehow
zyre_set_verbose (node);
zyre_start (node);
zclock_sleep(1000);
if(cert) {
zyre_set_curve_keypair(node, zcert_public_txt(cert), zcert_secret_txt(cert));
}
zyre_set_endpoint(node, "%s", endpoint);
const char *uuid = zyre_uuid (node);
printf("My uuid is %s\n", uuid);
if(cert) {
char *published_endpoint = zsys_sprintf("%s|%s", endpoint, zcert_public_txt(cert));
zsimpledisco_publish(disco, published_endpoint, uuid);
} else {
zsimpledisco_publish(disco, endpoint, uuid);
}
//zyre_join (node, "CHAT");
zsock_signal (pipe, 0); // Signal "ready" to caller
//zclock_sleep(1000);
bool terminated = false;
zpoller_t *poller = zpoller_new (pipe, zyre_socket (node), zsimpledisco_socket(disco), control, NULL);
while (!terminated) {
void *which = zpoller_wait (poller, 5000);
if (which == pipe) {
zmsg_t *msg = zmsg_recv (which);
if (!msg)
break; // Interrupted
char *command = zmsg_popstr (msg);
if (streq (command, "$TERM"))
terminated = true;
else {
puts ("E: invalid message to actor");
assert (false);
}
free (command);
zmsg_destroy (&msg);
}
else
if (which == zyre_socket (node)) {
zmsg_t *msg = zmsg_recv (which);
char *event = zmsg_popstr (msg);
char *peer = zmsg_popstr (msg);
char *name = zmsg_popstr (msg);
char *group = zmsg_popstr (msg);
char *message = zmsg_popstr (msg);
if (streq (event, "SHOUT")) {
//zsys_debug("zyre->pub %s: %s: %s", group, name, message);
zstr_sendx (pub, group, name, message, NULL);
}
free (event);
free (peer);
free (name);
free (group);
free (message);
zmsg_destroy (&msg);
}
else
if (which == zsimpledisco_socket (disco)) {
zmsg_t *msg = zmsg_recv (which);
char *key = zmsg_popstr (msg);
char *value = zmsg_popstr (msg);
zsys_debug("Discovered data: key='%s' value='%s'", key, value);
if(strneq(endpoint, key) && strneq(uuid, value)) {
zyre_require_peer (node, value, key);
maybe_create_untrusted_key(certstore, certstore_untrusted, public_key_dir_path, untrusted_public_key_dir_path, zsys_public_key_from_endpoint(key));
}
free (key);
free (value);
zmsg_destroy (&msg);
}
else
if (which == control) {
zmsg_t *msg = zmsg_recv (which);
//zsys_debug("Got message from control socket");
//zmsg_print(msg);
zframe_t *routing_id = zmsg_pop(msg);
char *command = zmsg_popstr (msg);
if (streq (command, "SUB")) {
char *group = zmsg_popstr (msg);
zsys_debug("Joining %s", group);
zyre_join (node, group);
free(group);
}
else
if (streq (command, "PUB")) {
char *group = zmsg_popstr (msg);
char *str = zmsg_popstr (msg);
//zsys_debug("pub->zyre %s: %s", group, str);
zyre_shouts (node, group, "%s", str);
zstr_sendx (pub, group, "local", str, NULL);
free(group);
free(str);
}
zframe_destroy(&routing_id);
zstr_free(&command);
zmsg_destroy(&msg);
}
if(zclock_mono() - last_bootstrap > 30*1000) {
bootstrap_simpledisco(disco, certstore);
last_bootstrap = zclock_mono();
}
}
zpoller_destroy (&poller);
zyre_stop (node);
zclock_sleep (100);
zyre_destroy (&node);
}
int
gateway_cmd (char *node_name)
{
zactor_t *actor = zactor_new (gateway_actor, node_name);
assert (actor);
while (!zsys_interrupted) {
zclock_sleep(1000);
}
zactor_destroy (&actor);
return 0;
}
#ifndef __GATEWAY_H_INCLUDED__
#define __GATEWAY_H_INCLUDED__
int server_cmd(char *bind);
int keygen_cmd(const char *keypair_filename);
int gateway_cmd (char *node_name);
#endif
#include "czmq_library.h"
// https://stackoverflow.com/questions/744766/how-to-compare-ends-of-strings-in-c
int EndsWith(const char *str, const char *suffix)
{
if (!str || !suffix)
return 0;
size_t lenstr = strlen(str);
size_t lensuffix = strlen(suffix);
if (lensuffix > lenstr)
return 0;
return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0;
}
int keygen_cmd(const char *filename)
{
char *keypair_filename;
const char *keypair_filename_secret;
// The next bit of code ensures that keypair_filename is 'foo' and keypair_filename_secret is 'foo_secret'
// FIXME: this leaks the filenames
if(EndsWith(filename, "_secret")) {
keypair_filename_secret = filename;
keypair_filename = strdup(filename);
char *ptr = keypair_filename + strlen(keypair_filename) - strlen("_secret");
*ptr = '\0';
} else {
keypair_filename = (char *) filename;
keypair_filename_secret = zsys_sprintf("%s_secret", filename);
}
if( access( keypair_filename, F_OK ) != -1 ) {
zsys_info("%s already exists, not creating keys", keypair_filename);
return 0;
}
if( access( keypair_filename_secret, F_OK ) != -1 ) {
zsys_info("%s already exists, not creating keys", keypair_filename);
return 0;
}
zcert_t *cert = zcert_new();
if(!cert) {
perror("Error creating new certificate");
return 1;
}
if(-1 == zcert_save(cert, keypair_filename)) {
zsys_info("Attempting to write keys to %s and %s", keypair_filename, keypair_filename_secret);
perror("Error writing key");
return 1;
}
zsys_info("Keys written to %s and %s", keypair_filename, keypair_filename_secret);
return 0;
}
#include "czmq_library.h"
#include "zsimpledisco.h"
#include "gateway.h"
void usage(char *cmd)
{
fprintf(stderr, "Usage: \n");
fprintf(stderr, " %s node_name\n", cmd);
fprintf(stderr, " %s keygen\n", cmd);
fprintf(stderr, " %s disco tcp://*:9999\n\n", cmd);
fprintf(stderr, "Environment Variables and their defaults:\n"
"UNTRUSTED_PUBLIC_KEY_DIR_PATH ./public_keys_untrusted path to directory to store new public keys\n"
"PRIVATE_KEY_PATH client.key_secret path to private key\n"
"PUBLIC_KEY_DIR_PATH ./public_keys path to directory containing public keys\n"
"ZYRE_BIND tcp://*:5670 the endpoint that the zyre p2p socket should bind to\n"
"DISABLE_CURVE unset set to disable curve encryption for sockets\n"
"PUBSUB_ENDPOINT tcp://127.0.0.1:14000 the endpoint that the gateway should bind to for pubsub\n"
"CONTROL_ENDPOINT tcp://127.0.0.1:14001 the endpoint that the gateway should bind to for control\n"
);
exit (1);
}
int
main (int argc, char *argv [])
{
zsys_init();
if (argc < 2) {
usage(argv[0]);
}
const char *private_key_path = getenv("PRIVATE_KEY_PATH");
if(!private_key_path) {
private_key_path = "client.key_secret";
zsys_info("PRIVATE_KEY_PATH defaulted to '%s'", private_key_path);
}
if (!zsys_file_exists(private_key_path)) {
keygen_cmd(private_key_path);
}
if (argc == 2 && streq(argv[1], "keygen")) {
exit(keygen_cmd(private_key_path));
}
if (argc == 2 && streq(argv[1], "disco")) {
usage(argv[0]);
}
if (argc == 3 && streq(argv[1], "disco")) {
exit(server_cmd(argv[2]));
}
return gateway_cmd(argv[1]);
}
# **** Generated on 2017-07-25 09:29:37 by CZMQ ****
# ZeroMQ CURVE Public Certificate
# Exchange securely, or use a secure mechanism to verify the contents
# of this file after exchange. Store public certificates in your home
# directory, in the .curve subdirectory.
metadata
simpledisco-endpoint = "tcp://cabana.ncsa.illinois.edu:9999"
curve
public-key = ").rnGhuU8zQr&rAyt^DF6+7l45!avpLher:M2{gm"
#!/usr/bin/env python
import logging
import os
import sys
import random
import zmq
import zmq.auth
from zmq.auth.thread import ThreadAuthenticator
import time
import uuid
import json
def make_client(ctx, endpoint):
client = ctx.socket(zmq.REQ)
# We need two certificates, one for the client and one for
# the server. The client must know the server's public key
# to make a CURVE connection.
client_secret_file = os.path.join('private_keys', "client.key_secret")
client_public, client_secret = zmq.auth.load_certificate(client_secret_file)
client.curve_secretkey = client_secret
client.curve_publickey = client_public
server_public_file = os.path.join('public_keys', "server.key")
server_public, _ = zmq.auth.load_certificate(server_public_file)
# The client must know the server's public key to make a CURVE connection.
client.curve_serverkey = server_public
client.connect(endpoint)
return client
def client(server_endpoints, my_id, my_port):
print("Client starting...")
ctx = zmq.Context.instance()
clients = {srv: make_client(ctx, srv) for srv in server_endpoints}
while True:
all_peers = {}
for srv, client in clients.items():
client.send_multipart([b"PUBLISH", my_id, my_port])
if not client.poll(2000):
print("DEAD:", srv)
clients[srv] = make_client(ctx, srv)
continue
msg = client.recv()
print(msg)
client.send_multipart([b"PEERS"])
if not client.poll(2000):
print("DEAD:", srv)
clients[srv] = make_client(ctx, srv)
continue
peers = json.loads(client.recv().decode('utf-8'))
print("peers from", srv)
for U, val in peers:
print("-", U, val)
all_peers[U] = val
print()
print("All peers:")
for u, val in all_peers.items():
print("-", u, val)
print()
time.sleep(2)
if __name__ == '__main__':
if zmq.zmq_version_info() < (4,0):
raise RuntimeError("Security is not supported in libzmq version < 4.0. libzmq version {0}".format(zmq.zmq_version()))
if '-v' in sys.argv:
level = logging.DEBUG
else:
level = logging.INFO
logging.basicConfig(level=level, format="[%(levelname)s] %(message)s")
servers = sys.argv[1:]
my_id = str(uuid.uuid4()).encode('utf-8')
my_port = str(random.randint(2000,2020)).encode('utf-8')
while True:
client(servers, my_id, my_port)
#!/usr/bin/env python
import logging
import os
import sys
import random
import zmq
import zmq.auth
from zmq.auth.thread import ThreadAuthenticator
import time
import uuid
import json
def make_client(ctx, endpoint):
client = ctx.socket(zmq.DEALER)
client.connect(endpoint)
return client
# We need two certificates, one for the client and one for
# the server. The client must know the server's public key
# to make a CURVE connection.
client_secret_file = os.path.join('private_keys', "client.key_secret")
client_public, client_secret = zmq.auth.load_certificate(client_secret_file)
client.curve_secretkey = client_secret
client.curve_publickey = client_public
server_public_file = os.path.join('public_keys', "server.key")
server_public, _ = zmq.auth.load_certificate(server_public_file)
# The client must know the server's public key to make a CURVE connection.
client.curve_serverkey = server_public
client.connect(endpoint)
return client
def client(server_endpoints, my_id, my_port):
print("Client starting...")
ctx = zmq.Context.instance()
clients = {srv: make_client(ctx, srv) for srv in server_endpoints}