Scroll to navigation

ZAUTH(3) CZMQ Manual ZAUTH(3)

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 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 '@interface' section in './../src/zauth.c'.

DESCRIPTION

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.

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); // 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\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
03/02/2024 CZMQ 4.2.1