Provided by: libczmq-dev_4.1.0-2_amd64 bug

NAME

       zauth - Class for authentication for ZeroMQ security mechanisms

SYNOPSIS

       #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 (whitelist) 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 whitelist more IP addresses. If you whitelist one
       //  or more addresses, any non-whitelisted addresses are treated as
       //  blacklisted:
       //
       //      zstr_sendx (auth, "ALLOW", "127.0.0.1", "127.0.0.2", NULL);
       //      zsock_wait (auth);
       //
       //  Deny (blacklist) a list of IP addresses. For all security mechanisms,
       //  this rejects the connection without any further authentication. Use
       //  either a whitelist, or a blacklist, not not both. If you define both
       //  a whitelist and a blacklist, only the whitelist 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 '@interface' section in './../src/zauth.c'.

DESCRIPTION

       A zauth actor takes over authentication for all incoming connections in its context. You
       can whitelist or blacklist peers based on IP address, and define policies for securing
       PLAIN, CURVE, and GSSAPI connections.

       This class replaces zauth_v2, and is meant for applications that use the CZMQ v3 API
       (meaning, zsock).

EXAMPLE

       From zauth_test method.

           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's 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's 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);

           //  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, true);
           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, 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\n");
           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'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);
               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

AUTHORS

       The czmq manual was written by the authors in the AUTHORS file.

RESOURCES

       Main web site:

       Report bugs to the email <zeromq-dev@lists.zeromq.org[1]>

COPYRIGHT

       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.

NOTES

        1. zeromq-dev@lists.zeromq.org
           mailto:zeromq-dev@lists.zeromq.org