void HHVM_METHOD(ZMQAuth, __construct, const Object& contextObj) { auto auth = Native::data<ZMQAuth>(this_); auto ctx = Native::data<ZMQContext>(contextObj); // NOTE (phuedx, 2014-05-14): A zauth object needs a context so that it // can take over authentication for all incoming connections in that // context. Creating a shadow context from the specified context allows // us to continue working with CZMQ. auth->shadow_context = zctx_shadow_zmq_ctx(ctx->context->z_ctx); if (!auth->shadow_context) { throwExceptionClass(s_ZMQAuthExceptionClass, "Failed to create the underlying shadow context object.", PHP_ZMQ_INTERNAL_ERROR); } auth->zauth = zauth_new(auth->shadow_context); if (!auth->zauth) { throwExceptionClass(s_ZMQAuthExceptionClass, "Failed to create the underlying zauth object.", PHP_ZMQ_INTERNAL_ERROR); } }
int main (void) { // Create context zctx_t *ctx = zctx_new (); // Start an authentication engine for this context. This engine // allows or denies incoming connections (talking to the libzmq // core over a protocol called ZAP). zauth_t *auth = zauth_new (ctx); // Get some indication of what the authenticator is deciding zauth_set_verbose (auth, true); // Whitelist our address; any other address will be rejected zauth_allow (auth, "127.0.0.1"); // Create and bind server socket void *server = zsocket_new (ctx, ZMQ_PUSH); zsocket_set_zap_domain (server, "global"); zsocket_bind (server, "tcp://*:9000"); // Create and connect client socket void *client = zsocket_new (ctx, ZMQ_PULL); zsocket_connect (client, "tcp://127.0.0.1:9000"); // Send a single message from server to client zstr_send (server, "Hello"); char *message = zstr_recv (client); assert (streq (message, "Hello")); free (message); puts ("Strawhouse test OK"); zauth_destroy (&auth); zctx_destroy (&ctx); return 0; }
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; }
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; }
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"); }
static void * server_task (void *args) { bool verbose = *((bool *) args); // 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); void *router = zsocket_new (ctx, ZMQ_ROUTER); int rc = zsocket_bind (router, "tcp://127.0.0.1:9005"); assert (rc != -1); zcert_t *server_cert = zcert_load (TESTDIR "/server.cert"); assert (server_cert); curve_codec_t *server = curve_codec_new_server (server_cert, ctx); assert (server); zcert_destroy (&server_cert); curve_codec_set_verbose (server, verbose); // Set some metadata properties curve_codec_set_metadata (server, "Server", "CURVEZMQ/curve_codec"); // Execute incoming frames until ready or exception // In practice we'd want a server instance per unique client while (!curve_codec_connected (server)) { zframe_t *sender = zframe_recv (router); zframe_t *input = zframe_recv (router); assert (input); zframe_t *output = curve_codec_execute (server, &input); assert (output); zframe_send (&sender, router, ZFRAME_MORE); zframe_send (&output, router, 0); } // Check client metadata char *client_name = (char *) zhash_lookup (curve_codec_metadata (server), "client"); assert (client_name); assert (streq (client_name, "CURVEZMQ/curve_client")); bool finished = false; while (!finished) { // Now act as echo service doing a full decode and encode zframe_t *sender = zframe_recv (router); zframe_t *encrypted = zframe_recv (router); assert (encrypted); zframe_t *cleartext = curve_codec_decode (server, &encrypted); assert (cleartext); if (memcmp (cleartext, "END", 3) == 0) finished = true; // Echo message back encrypted = curve_codec_encode (server, &cleartext); assert (encrypted); zframe_send (&sender, router, ZFRAME_MORE); zframe_send (&encrypted, router, 0); } curve_codec_destroy (&server); zauth_destroy (&auth); zctx_destroy (&ctx); return NULL; }
int main(int argc, char **argv) { if( argc < 4 ) { printf("HEY! Usage:\n banshare-report [-d] <program-name> <jail-name> <banned-ip>\n\n"); printf(" where -d sets debug mode\n"); exit(1); } int baseind = 1; if( argv[1][0] == '-' && argv[1][1] == 'd') { debug = 1; baseind = 2; } char *progname = argv[baseind]; char *jailname = argv[baseind+1]; char *bannedip = argv[baseind+2]; zauth_t *auth; zcert_t *cert; zcert_t *server_public_cert; char certdir[256]; char servercert[512]; if (access("/etc/ssl/certs/banshare/", R_OK) == 0 ) { // ubuntu, CentOS 6.x strcpy(certdir, "/etc/ssl/certs/banshare"); strcpy(servercert, "/etc/ssl/certs/banshare/server_banshare"); } else if (access("/etc/pki/tls/certs/banshare/", R_OK) == 0 ) { // CentOS 5.x strcpy(certdir, "/etc/pki/tls/certs/banshare"); strcpy(servercert, "/etc/pki/tls/certs/banshare/server_banshare"); } zctx_t *ctx = zctx_new(); if (enc) { auth = zauth_new (ctx); zauth_set_verbose (auth, true); zauth_configure_curve (auth, "*", certdir); cert = zcert_new_from(banshare_client_public, banshare_client_private); server_public_cert = zcert_load(servercert); } void *rep_sock = zsocket_new(ctx, ZMQ_REQ); // This will be request socket to complement the server's REP socket! if (enc) { zcert_apply (cert, rep_sock); zsocket_set_curve_serverkey (rep_sock, zcert_public_txt(server_public_cert)); } zsocket_set_rcvtimeo(rep_sock, 3000); // set read and write timeouts to 3 sec. zsocket_set_sndtimeo(rep_sock, 3000); int rc; char *servip; if (server_is_local()) { servip = "127.0.0.1"; } else { servip = BANSHARE_SERVER_IP; } rc = zsocket_connect(rep_sock, "tcp://%s:%d", servip, SERVER_REPORT_PORT); if (rc != 0) { printf("Connect to REQ socket to %s:%d FAILED with rc=%d\n", servip, SERVER_REPORT_PORT, rc); exit(0); } if (debug) printf("Connected to tcp://%s:%d Just fine...\n", servip, SERVER_REPORT_PORT); zclock_sleep(500); while (!zctx_interrupted) { char buf[1000]; int ret1 = zstr_sendf(rep_sock, "%s;%s;%s;%s", progname, jailname, bannedip, this_ip); if (ret1 == -1) { printf("Timeout while sending report! Server is DOWN?\n"); exit(1); } if( debug) printf("Sent: %s;%s;%s;%s to %s\n", progname, jailname, bannedip, this_ip, servip); // and like all good req-rep sockets, we should get a response! char *rec = zstr_recv(rep_sock); if (!rec) { printf("Timeout while waiting for OK! Server is DOWN?\n"); exit(1); } if (debug) printf("Got %s back from server\n", rec); zstr_free(&rec); // Oh, all that was really difficult, wasn't it? we are done. disconnect and exit exit(0); } }