'\" t .\" Title: zauth .\" Author: [see the "AUTHORS" section] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 01/17/2021 .\" Manual: CZMQ Manual .\" Source: CZMQ 4.2.1 .\" Language: English .\" .TH "ZAUTH" "3" "01/17/2021" "CZMQ 4\&.2\&.1" "CZMQ Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" zauth \- Class for authentication for ZeroMQ security mechanisms .SH "SYNOPSIS" .sp .nf #define CURVE_ALLOW_ANY "*" // CZMQ v3 API (for use with zsock, not zsocket, which is deprecated)\&. // // Create new zauth actor instance\&. This installs authentication on all // zsock sockets\&. Until you add policies, all incoming NULL connections are // allowed (classic ZeroMQ behaviour), and all PLAIN and CURVE connections // are denied: // // zactor_t *auth = zactor_new (zauth, NULL); // // Destroy zauth instance\&. This removes authentication and allows all // connections to pass, without authentication: // // zactor_destroy (&auth); // // Note that all zauth commands are synchronous, so your application always // waits for a signal from the actor after each command\&. // // Enable verbose logging of commands and activity\&. Verbose logging can help // debug non\-trivial authentication policies: // // zstr_send (auth, "VERBOSE"); // zsock_wait (auth); // // Allow a list of IP addresses\&. For NULL, all clients from // these addresses will be accepted\&. For PLAIN and CURVE, they will be // allowed to continue with authentication\&. You can call this method // multiple times to allow more IP addresses\&. If you allow one // or more addresses, any non\-allowed addresses are treated as // blocked: // // zstr_sendx (auth, "ALLOW", "127\&.0\&.0\&.1", "127\&.0\&.0\&.2", NULL); // zsock_wait (auth); // // Deny (block) a list of IP addresses\&. For all security mechanisms, // this rejects the connection without any further authentication\&. Use // either an allowed list, or a blocked list, not not both\&. If you define both // an allowed list and a blocked list, only the allowed list takes effect: // // zstr_sendx (auth, "DENY", "192\&.168\&.0\&.1", "192\&.168\&.0\&.2", NULL); // zsock_wait (auth); // // Configure PLAIN authentication using a plain\-text password file\&. You can // modify the password file at any time; zauth will reload it automatically // if modified externally: // // zstr_sendx (auth, "PLAIN", filename, NULL); // zsock_wait (auth); // // Configure CURVE authentication, using a directory that holds all public // client certificates, i\&.e\&. their public keys\&. The certificates must be in // zcert_save format\&. You can add and remove certificates in that directory // at any time\&. To allow all client keys without checking, specify // CURVE_ALLOW_ANY for the directory name: // // zstr_sendx (auth, "CURVE", directory, NULL); // zsock_wait (auth); // // Configure GSSAPI authentication, using an underlying mechanism (usually // Kerberos) to establish a secure context and perform mutual authentication: // // zstr_sendx (auth, "GSSAPI", NULL); // zsock_wait (auth); // // This is the zauth constructor as a zactor_fn: CZMQ_EXPORT void zauth (zsock_t *pipe, void *certstore); // Selftest CZMQ_EXPORT void zauth_test (bool verbose); Please add \*(Aq@interface\*(Aq section in \*(Aq\&./\&.\&./src/zauth\&.c\*(Aq\&. .fi .SH "DESCRIPTION" .sp A zauth actor takes over authentication for all incoming connections in its context\&. You can allow or block peers based on IP address, and define policies for securing PLAIN, CURVE, and GSSAPI connections\&. .sp This class replaces zauth_v2, and is meant for applications that use the CZMQ v3 API (meaning, zsock)\&. .SH "EXAMPLE" .PP \fBFrom zauth_test method\fR. .sp .if n \{\ .RS 4 .\} .nf const char *SELFTEST_DIR_RW = "src/selftest\-rw"; const char *testbasedir = "\&.test_zauth"; const char *testpassfile = "password\-file"; const char *testcertfile = "mycert\&.txt"; char *basedirpath = NULL; // subdir in a test, under SELFTEST_DIR_RW char *passfilepath = NULL; // pathname to testfile in a test, in dirpath char *certfilepath = NULL; // pathname to testfile in a test, in dirpath basedirpath = zsys_sprintf ("%s/%s", SELFTEST_DIR_RW, testbasedir); assert (basedirpath); passfilepath = zsys_sprintf ("%s/%s", basedirpath, testpassfile); assert (passfilepath); certfilepath = zsys_sprintf ("%s/%s", basedirpath, testcertfile); assert (certfilepath); // 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 (passfilepath); zsys_file_delete (certfilepath); zsys_dir_delete (basedirpath); // Create temporary directory for test files zsys_dir_create (basedirpath); // Check there\*(Aqs no authentication zsock_t *server = zsock_new (ZMQ_PULL); assert (server); zsock_t *client = zsock_new (ZMQ_PUSH); assert (client); bool success = s_can_connect (&server, &client, true); 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\*(Aqs no authentication on a default NULL server success = s_can_connect (&server, &client, true); 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, true); assert (success); // Block 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, true); assert (!success); // Allow our address, which overrides the block list zsock_set_zap_domain (server, "global"); zstr_sendx (auth, "ALLOW", "127\&.0\&.0\&.1", NULL); zsock_wait (auth); success = s_can_connect (&server, &client, true); assert (success); // Try PLAIN authentication zsock_set_zap_domain (server, "global"); zsock_set_plain_server (server, 1); zsock_set_plain_username (client, "admin"); zsock_set_plain_password (client, "Password"); success = s_can_connect (&server, &client, true); assert (!success); FILE *password = fopen (passfilepath, "w"); assert (password); fprintf (password, "admin=Password\en"); fclose (password); zsock_set_zap_domain (server, "global"); zsock_set_plain_server (server, 1); zsock_set_plain_username (client, "admin"); zsock_set_plain_password (client, "Password"); zstr_sendx (auth, "PLAIN", passfilepath, NULL); zsock_wait (auth); success = s_can_connect (&server, &client, false); assert (success); #if (ZMQ_VERSION >= ZMQ_MAKE_VERSION (4, 1, 0)) // Test that the User\-Id metadata is present zframe_t *frame = zframe_recv (server); assert (frame != NULL); const char *user_id = zframe_meta (frame, "User\-Id"); assert (user_id != NULL); assert (streq (user_id, "admin")); zframe_destroy (&frame); #endif s_renew_sockets(&server, &client); zsock_set_zap_domain (server, "global"); zsock_set_plain_server (server, 1); zsock_set_plain_username (client, "admin"); zsock_set_plain_password (client, "Bogus"); success = s_can_connect (&server, &client, true); assert (!success); if (zsys_has_curve ()) { // Try CURVE authentication // We\*(Aqll create two new certificates and save the client public // certificate on disk; in a real case we\*(Aqd 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); const 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); zsock_set_zap_domain (server, "global"); success = s_can_connect (&server, &client, true); 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, true); assert (success); // Test full client authentication using certificates zcert_set_meta (client_cert, "Hello", "%s", "World!"); 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, certfilepath); zstr_sendx (auth, "CURVE", basedirpath, NULL); zsock_wait (auth); zsock_set_zap_domain (server, "global"); success = s_can_connect (&server, &client, false); assert (success); #if (ZMQ_VERSION >= ZMQ_MAKE_VERSION (4, 1, 0)) // Test send/recv certificate metadata zframe_t *frame = zframe_recv (server); assert (frame != NULL); const char *meta = zframe_meta (frame, "Hello"); assert (meta != NULL); assert (streq (meta, "World!")); const char *user_id = zframe_meta (frame, "User\-Id"); assert (user_id != NULL); assert (streq (user_id, zcert_public_txt(client_cert))); zframe_destroy (&frame); s_renew_sockets(&server, &client); #endif zcert_destroy (&server_cert); zcert_destroy (&client_cert); // Test custom zcertstore zcertstore_t *certstore = zcertstore_new (NULL); zcertstore_set_loader (certstore, s_test_loader, NULL, NULL); zactor_destroy(&auth); auth = zactor_new (zauth, certstore); assert (auth); if (verbose) { zstr_sendx (auth, "VERBOSE", NULL); zsock_wait (auth); } byte public_key [32] = { 105, 76, 150, 58, 214, 191, 218, 65, 50, 172, 131, 188, 247, 211, 136, 170, 227, 26, 57, 170, 185, 63, 246, 225, 177, 230, 12, 8, 134, 136, 105, 106 }; byte secret_key [32] = { 245, 217, 172, 73, 106, 28, 195, 17, 218, 132, 135, 209, 99, 240, 98, 232, 7, 137, 244, 100, 242, 23, 29, 114, 70, 223, 83, 1, 113, 207, 132, 149 }; zcert_t *shared_cert = zcert_new_from (public_key, secret_key); assert (shared_cert); zcert_apply (shared_cert, server); zcert_apply (shared_cert, client); zsock_set_curve_server (server, 1); zsock_set_curve_serverkey (client, "x?T*N/1Y{8goubv{Ts}#&#f}TXJ//DVe#D2HkoLU"); success = s_can_connect (&server, &client, true); assert (success); zcert_destroy (&shared_cert); } // Remove the authenticator and check a normal connection works zactor_destroy (&auth); success = s_can_connect (&server, &client, true); assert (success); zsock_destroy (&client); zsock_destroy (&server); // Delete all test files dir = zdir_new (basedirpath, NULL); assert (dir); zdir_remove (dir, true); zdir_destroy (&dir); zstr_free (&passfilepath); zstr_free (&certfilepath); zstr_free (&basedirpath); #endif #if defined (__WINDOWS__) zsys_shutdown(); #endif .fi .if n \{\ .RE .\} .sp .SH "AUTHORS" .sp The czmq manual was written by the authors in the AUTHORS file\&. .SH "RESOURCES" .sp Main web site: \m[blue]\fB\%\fR\m[] .sp Report bugs to the email <\m[blue]\fBzeromq\-dev@lists\&.zeromq\&.org\fR\m[]\&\s-2\u[1]\d\s+2> .SH "COPYRIGHT" .sp Copyright (c) the Contributors as noted in the AUTHORS file\&. This file is part of CZMQ, the high\-level C binding for 0MQ: http://czmq\&.zeromq\&.org\&. This Source Code Form is subject to the terms of the Mozilla Public License, v\&. 2\&.0\&. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla\&.org/MPL/2\&.0/\&. LICENSE included with the czmq distribution\&. .SH "NOTES" .IP " 1." 4 zeromq-dev@lists.zeromq.org .RS 4 \%mailto:zeromq-dev@lists.zeromq.org .RE