zauth(3)
========

NAME
----
zauth - authentication for ZeroMQ security mechanisms

SYNOPSIS
--------
----
#define CURVE_ALLOW_ANY "*"

//  Constructor
//  Install authentication for the specified context. Returns a new zauth
//  object that you can use to configure authentication. Note that until you
//  add policies, all incoming NULL connections are allowed (classic ZeroMQ
//  behaviour), and all PLAIN and CURVE connections are denied. If there was
//  an error during initialization, returns NULL.
CZMQ_EXPORT zauth_t *
    zauth_new (zctx_t *ctx);
    
//  Allow (whitelist) a single IP address. For NULL, all clients from this
//  address will be accepted. For PLAIN and CURVE, they will be allowed to
//  continue with authentication. You can call this method multiple times 
//  to whitelist multiple IP addresses. If you whitelist a single address,
//  any non-whitelisted addresses are treated as blacklisted.
CZMQ_EXPORT void
    zauth_allow (zauth_t *self, char *address);

//  Deny (blacklist) a single IP address. 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.
CZMQ_EXPORT void
    zauth_deny (zauth_t *self, char *address);

//  Configure PLAIN authentication for a given domain. PLAIN authentication
//  uses a plain-text password file. The filename is treated as a printf 
//  format. To cover all domains, use "*". You can modify the password file
//  at any time; it is reloaded automatically.
CZMQ_EXPORT void
    zauth_configure_plain (zauth_t *self, char *domain, char *filename, ...);
    
//  Configure CURVE authentication for a given domain. CURVE authentication
//  uses a directory that holds all public client certificates, i.e. their
//  public keys. The certificates must be in zcert_save () format. The 
//  location is treated as a printf format. To cover all domains, use "*". 
//  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 location.
CZMQ_EXPORT void
    zauth_configure_curve (zauth_t *self, char *domain, char *location, ...);
    
//  Enable verbose tracing of commands and activity
CZMQ_EXPORT void
    zauth_set_verbose (zauth_t *self, bool verbose);
    
//  Destructor
CZMQ_EXPORT void
    zauth_destroy (zauth_t **self_p);

//  Selftest
CZMQ_EXPORT int
    zauth_test (bool verbose);
----

DESCRIPTION
-----------

A zauth object takes over authentication for all incoming connections in 
its context. Note that libzmq provides four levels of security: default 
NULL (which zauth does not see), and authenticated NULL, PLAIN, and CURVE,
which zauth can see.



EXAMPLE
-------
.From zauth_test method
----
    //  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);
----

SEE ALSO
--------
linkczmq:czmq[7]
