zauth(3)
Class for authentication for ZeroMQ security mechanisms
Description
ZAUTH
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