1 /*  =========================================================================
2     zauth - authentication for ZeroMQ security mechanisms
3 
4     Copyright (c) the Contributors as noted in the AUTHORS file.
5     This file is part of CZMQ, the high-level C binding for 0MQ:
6     http://czmq.zeromq.org.
7 
8     This Source Code Form is subject to the terms of the Mozilla Public
9     License, v. 2.0. If a copy of the MPL was not distributed with this
10     file, You can obtain one at http://mozilla.org/MPL/2.0/.
11     =========================================================================
12 */
13 
14 /*
15 @header
16     A zauth actor takes over authentication for all incoming connections in
17     its context. You can allow or block peers based on IP address,
18     and define policies for securing PLAIN, CURVE, and GSSAPI connections.
19 @discuss
20     This class replaces zauth_v2, and is meant for applications that use the
21     CZMQ v3 API (meaning, zsock).
22 @end
23 */
24 
25 #include "czmq_classes.h"
26 #define ZAP_ENDPOINT  "inproc://zeromq.zap.01"
27 
28 //  --------------------------------------------------------------------------
29 //  The self_t structure holds the state for one actor instance
30 
31 typedef struct {
32     zsock_t *pipe;              //  Actor command pipe
33     zsock_t *handler;           //  ZAP handler socket
34     zhashx_t *allowlist;        //  Allowed addresses
35     zhashx_t *blocklist;        //  Blocked addresses
36     zhashx_t *passwords;        //  PLAIN passwords, if loaded
37     zpoller_t *poller;          //  Socket poller
38     zcertstore_t *certstore;    //  CURVE certificate store, if loaded
39     bool allow_any;             //  CURVE allows arbitrary clients
40     bool terminated;            //  Did caller ask us to quit?
41     bool verbose;               //  Verbose logging enabled?
42 } self_t;
43 
44 static void
s_self_destroy(self_t ** self_p)45 s_self_destroy (self_t **self_p)
46 {
47     assert (self_p);
48     if (*self_p) {
49         self_t *self = *self_p;
50         zhashx_destroy (&self->passwords);
51         zhashx_destroy (&self->allowlist);
52         zhashx_destroy (&self->blocklist);
53         zcertstore_destroy (&self->certstore);
54         zpoller_destroy (&self->poller);
55         if (self->handler) {
56             zsock_unbind (self->handler, ZAP_ENDPOINT);
57             zsock_destroy (&self->handler);
58         }
59         freen (self);
60         *self_p = NULL;
61     }
62 }
63 
64 static self_t *
s_self_new(zsock_t * pipe,zcertstore_t * certstore)65 s_self_new (zsock_t *pipe, zcertstore_t *certstore)
66 {
67     self_t *self = (self_t *) zmalloc (sizeof (self_t));
68     assert (self);
69     if (certstore) {
70         self->certstore = certstore;
71         self->allow_any = false;
72     }
73     self->pipe = pipe;
74     self->allowlist = zhashx_new ();
75     assert (self->allowlist);
76     self->blocklist = zhashx_new ();
77 
78     //  Create ZAP handler and get ready for requests
79     assert (self->blocklist);
80     self->handler = zsock_new (ZMQ_REP);
81     assert (self->handler);
82     int rc = zsock_bind (self->handler, ZAP_ENDPOINT);
83     assert (rc == 0);
84     self->poller = zpoller_new (self->pipe, self->handler, NULL);
85     assert (self->poller);
86 
87     return self;
88 }
89 
90 
91 //  --------------------------------------------------------------------------
92 //  Handle a command from calling application
93 
94 static int
s_self_handle_pipe(self_t * self)95 s_self_handle_pipe (self_t *self)
96 {
97     //  Get the whole message off the pipe in one go
98     zmsg_t *request = zmsg_recv (self->pipe);
99     if (!request)
100         return -1;                  //  Interrupted
101 
102     char *command = zmsg_popstr (request);
103     if (self->verbose)
104         zsys_info ("zauth: API command=%s", command);
105 
106     if (streq (command, "ALLOW")) {
107         char *address = zmsg_popstr (request);
108         while (address) {
109             if (self->verbose)
110                 zsys_info ("zauth: - allowlisting ipaddress=%s", address);
111             zhashx_insert (self->allowlist, address, "OK");
112             zstr_free (&address);
113             address = zmsg_popstr (request);
114         }
115         zsock_signal (self->pipe, 0);
116     }
117     else
118     if (streq (command, "DENY")) {
119         char *address = zmsg_popstr (request);
120         while (address) {
121             if (self->verbose)
122                 zsys_info ("zauth: - blocking ipaddress=%s", address);
123             zhashx_insert (self->blocklist, address, "OK");
124             zstr_free (&address);
125             address = zmsg_popstr (request);
126         }
127         zsock_signal (self->pipe, 0);
128     }
129     else
130     if (streq (command, "PLAIN")) {
131         //  Get password file and load into zhash table
132         //  If the file doesn't exist we'll get an empty table
133         char *filename = zmsg_popstr (request);
134         zhashx_destroy (&self->passwords);
135         self->passwords = zhashx_new ();
136         if (zhashx_load (self->passwords, filename) && self->verbose)
137             zsys_info ("zauth: could not load file=%s", filename);
138         zstr_free (&filename);
139         zsock_signal (self->pipe, 0);
140     }
141     else
142     if (streq (command, "CURVE")) {
143         //  If location is CURVE_ALLOW_ANY, allow all clients. Otherwise
144         //  treat location as a directory that holds the certificates.
145         char *location = zmsg_popstr (request);
146         if (streq (location, CURVE_ALLOW_ANY))
147             self->allow_any = true;
148         else {
149             zcertstore_destroy (&self->certstore);
150             // FIXME: what if this fails?
151             self->certstore = zcertstore_new (location);
152             self->allow_any = false;
153         }
154         zstr_free (&location);
155         zsock_signal (self->pipe, 0);
156     }
157     else
158     if (streq (command, "GSSAPI"))
159         //  GSSAPI authentication is not yet implemented here
160         zsock_signal (self->pipe, 0);
161     else
162     if (streq (command, "VERBOSE")) {
163         self->verbose = true;
164         zsock_signal (self->pipe, 0);
165     }
166     else
167     if (streq (command, "$TERM"))
168         self->terminated = true;
169     else {
170         zsys_error ("zauth: - invalid command: %s", command);
171         assert (false);
172     }
173     zstr_free (&command);
174     zmsg_destroy (&request);
175     return 0;
176 }
177 
178 
179 //  --------------------------------------------------------------------------
180 //  A small class for working with ZAP requests and replies.
181 //  Used internally in zauth to simplify working with RFC 27 messages.
182 
183 //  Structure of a ZAP request
184 
185 typedef struct {
186     zsock_t *handler;           //  Socket we're talking to
187     bool verbose;               //  Log ZAP requests and replies?
188     char *version;              //  Version number, must be "1.0"
189     char *sequence;             //  Sequence number of request
190     char *domain;               //  Server socket domain
191     char *address;              //  Client IP address
192     char *identity;             //  Server socket idenntity
193     char *mechanism;            //  Security mechansim
194     char *username;             //  PLAIN user name
195     char *password;             //  PLAIN password, in clear text
196     char *client_key;           //  CURVE client public key in ASCII
197     char *principal;            //  GSSAPI client principal
198     char *user_id;              //  User-Id to return in the ZAP Response
199 } zap_request_t;
200 
201 
202 static void
s_zap_request_destroy(zap_request_t ** self_p)203 s_zap_request_destroy (zap_request_t **self_p)
204 {
205     assert (self_p);
206     if (*self_p) {
207         zap_request_t *self = *self_p;
208         freen (self->version);
209         freen (self->sequence);
210         freen (self->domain);
211         freen (self->address);
212         freen (self->identity);
213         freen (self->mechanism);
214         freen (self->username);
215         freen (self->password);
216         freen (self->client_key);
217         freen (self->principal);
218         // self->user_id is a pointer to one of the above fields
219         freen (self);
220         *self_p = NULL;
221     }
222 }
223 
224 //  Receive a valid ZAP request from the handler socket
225 //  If the request was not valid, returns NULL.
226 
227 static zap_request_t *
s_zap_request_new(zsock_t * handler,bool verbose)228 s_zap_request_new (zsock_t *handler, bool verbose)
229 {
230     zap_request_t *self = (zap_request_t *) zmalloc (sizeof (zap_request_t));
231     if (!self)
232         return NULL;
233 
234     //  Store handler socket so we can send a reply easily
235     self->handler = handler;
236     self->verbose = verbose;
237     zmsg_t *request = zmsg_recv (handler);
238     if (!request) { // interrupted
239         s_zap_request_destroy (&self);
240         return NULL;
241     }
242 
243     //  Get all standard frames off the handler socket
244     self->version = zmsg_popstr (request);
245     self->sequence = zmsg_popstr (request);
246     self->domain = zmsg_popstr (request);
247     self->address = zmsg_popstr (request);
248     self->identity = zmsg_popstr (request);
249     self->mechanism = zmsg_popstr (request);
250 
251     //  If the version is wrong, we're linked with a bogus libzmq, so die
252     assert (streq (self->version, "1.0"));
253 
254     //  Get mechanism-specific frames
255     if (streq (self->mechanism, "PLAIN")) {
256         self->username = zmsg_popstr (request);
257         self->password = zmsg_popstr (request);
258     }
259     else
260     if (streq (self->mechanism, "CURVE")) {
261         zframe_t *frame = zmsg_pop (request);
262         assert (zframe_size (frame) == 32);
263         self->client_key = (char *) zmalloc (41);
264 #if (ZMQ_VERSION_MAJOR == 4)
265         zmq_z85_encode (self->client_key, zframe_data (frame), 32);
266 #endif
267         zframe_destroy (&frame);
268     }
269     else
270     if (streq (self->mechanism, "GSSAPI"))
271         self->principal = zmsg_popstr (request);
272 
273     if (self->verbose)
274         zsys_info ("zauth: ZAP request mechanism=%s ipaddress=%s",
275                    self->mechanism, self->address);
276     zmsg_destroy (&request);
277     return self;
278 }
279 
280 //  Send a ZAP reply to the handler socket
281 
282 static int
s_zap_request_reply(zap_request_t * self,char * status_code,char * status_text,unsigned char * metadata,size_t metasize)283 s_zap_request_reply (zap_request_t *self, char *status_code, char *status_text, unsigned char *metadata, size_t metasize)
284 {
285     if (self->verbose)
286         zsys_info ("zauth: - ZAP reply status_code=%s status_text=%s",
287                    status_code, status_text);
288 
289     zmsg_t *msg = zmsg_new ();
290     int rc = zmsg_addstr(msg, "1.0");
291     assert (rc == 0);
292     rc = zmsg_addstr(msg, self->sequence);
293     assert (rc == 0);
294     rc = zmsg_addstr(msg, status_code);
295     assert (rc == 0);
296     rc = zmsg_addstr(msg, status_text);
297     assert (rc == 0);
298     rc = zmsg_addstr(msg, self->user_id ? self->user_id : "");
299     assert (rc == 0);
300     rc = zmsg_addmem(msg, metadata, metasize);
301     assert (rc == 0);
302     rc = zmsg_send(&msg, self->handler);
303     assert (rc == 0);
304 
305     return 0;
306 }
307 
308 
309 //  --------------------------------------------------------------------------
310 //  Handle an authentication request from libzmq core
311 
312 //  Helper for s_add_property
313 //  THIS IS A COPY OF zmq::put_uint32 (<zmq>/src/wire.hpp)
314 
315 static void
s_put_uint32(unsigned char * buffer_,uint32_t value)316 s_put_uint32 (unsigned char *buffer_, uint32_t value)
317 {
318     buffer_ [0] = (unsigned char) (((value) >> 24) & 0xff);
319     buffer_ [1] = (unsigned char) (((value) >> 16) & 0xff);
320     buffer_ [2] = (unsigned char) (((value) >> 8) & 0xff);
321     buffer_ [3] = (unsigned char) (value & 0xff);
322 }
323 
324 //  Add metadata property to ptr
325 //  THIS IS AN ADAPTATION OF zmq::mechanism_t::add_property (<zmq>/src/mechanism.cpp)
326 
327 static size_t
s_add_property(unsigned char * ptr,const char * name,const void * value,size_t value_len)328 s_add_property (unsigned char *ptr, const char *name, const void *value, size_t value_len)
329 {
330     const size_t name_len = strlen (name);
331     assert (name_len <= 255);
332     *ptr++ = (unsigned char) name_len;
333     memcpy (ptr, name, name_len);
334     ptr += name_len;
335     assert (value_len <= 0x7FFFFFFF);
336     s_put_uint32 (ptr, (uint32_t) value_len);
337     ptr += 4;
338     memcpy (ptr, value, value_len);
339 
340     return 1 + name_len + 4 + value_len;
341 }
342 
343 static bool
s_authenticate_plain(self_t * self,zap_request_t * request)344 s_authenticate_plain (self_t *self, zap_request_t *request)
345 {
346     if (self->passwords) {
347         zhashx_refresh (self->passwords);
348         char *password = (char *) zhashx_lookup (self->passwords, request->username);
349         if (password && streq (password, request->password)) {
350             if (self->verbose)
351                 zsys_info ("zauth: - allowed (PLAIN) username=%s password=%s",
352                            request->username, request->password);
353             request->user_id = request->username;
354             return true;
355         }
356         else {
357             if (self->verbose)
358                 zsys_info ("zauth: - denied (PLAIN) username=%s password=%s",
359                            request->username, request->password);
360             return false;
361         }
362     }
363     else {
364         if (self->verbose)
365             zsys_info ("zauth: - denied (PLAIN) no password file defined");
366         return false;
367     }
368 }
369 
370 
371 static bool
s_authenticate_curve(self_t * self,zap_request_t * request,unsigned char ** metadata)372 s_authenticate_curve (self_t *self, zap_request_t *request, unsigned char **metadata)
373 {
374     if (self->allow_any) {
375         if (self->verbose)
376             zsys_info ("zauth: - allowed (CURVE allow any client)");
377         return true;
378     }
379     else
380     if (self->certstore) {
381         zcert_t *cert = zcertstore_lookup (self->certstore, request->client_key);
382         if (cert != NULL) {
383             zlist_t *meta_k = zcert_meta_keys (cert);
384             while (true) {
385                 void *key = zlist_next (meta_k);
386                 if (key == NULL) {
387                     break;
388                 }
389 
390                 const char *val = zcert_meta(cert, (const char *) key);
391                 if (val == NULL) {
392                     break;
393                 }
394 
395                 *metadata += s_add_property(*metadata, (const char *) key, val, strlen (val));
396             }
397             zlist_destroy (&meta_k);
398 
399             if (self->verbose)
400                 zsys_info ("zauth: - allowed (CURVE) client_key=%s", request->client_key);
401             request->user_id = request->client_key;
402             return true;
403         }
404     }
405 
406     if (self->verbose)
407         zsys_info ("zauth: - denied (CURVE) client_key=%s", request->client_key);
408     return false;
409 }
410 
411 static bool
s_authenticate_gssapi(self_t * self,zap_request_t * request)412 s_authenticate_gssapi (self_t *self, zap_request_t *request)
413 {
414     if (self->verbose)
415         zsys_info ("zauth: - allowed (GSSAPI) principal=%s identity=%s",
416                    request->principal, request->identity);
417     request->user_id = request->principal;
418     return true;
419 }
420 
421 //  TODO: allow regular expressions in addresses
422 static int
s_self_authenticate(self_t * self)423 s_self_authenticate (self_t *self)
424 {
425     zap_request_t *request = s_zap_request_new (self->handler, self->verbose);
426     if (!request)
427         return 0;           //  Interrupted, no request to process
428 
429     //  Is address explicitly allowed or blocked?
430     bool allowed = false;
431     bool denied = false;
432 
433     //  Curve certificate metadata
434     unsigned char * const metabuf = (unsigned char *) malloc (512);
435     assert (metabuf != NULL);
436     unsigned char *metadata = metabuf;
437 
438     if (zhashx_size (self->allowlist)) {
439         if (zhashx_lookup (self->allowlist, request->address)) {
440             allowed = true;
441             if (self->verbose)
442                 zsys_info ("zauth: - passed (allowed list) address=%s", request->address);
443         }
444         else {
445             denied = true;
446             if (self->verbose)
447                 zsys_info ("zauth: - denied (not in allowed list) address=%s", request->address);
448         }
449     }
450     else
451     if (zhashx_size (self->blocklist)) {
452         if (zhashx_lookup (self->blocklist, request->address)) {
453             denied = true;
454             if (self->verbose)
455                 zsys_info ("zauth: - denied (blocked list) address=%s", request->address);
456         }
457         else {
458             allowed = true;
459             if (self->verbose)
460                 zsys_info ("zauth: - passed (not in blocked list) address=%s", request->address);
461         }
462     }
463     //  Mechanism-specific checks
464     if (!denied) {
465         if (streq (request->mechanism, "NULL") && !allowed) {
466             //  For NULL, we allow if the address wasn't blocked
467             if (self->verbose)
468                 zsys_info ("zauth: - allowed (NULL)");
469             allowed = true;
470         }
471         else
472         if (streq (request->mechanism, "PLAIN"))
473             //  For PLAIN, even a allowlisted address must authenticate
474             allowed = s_authenticate_plain (self, request);
475         else
476         if (streq (request->mechanism, "CURVE"))
477             //  For CURVE, even a allowlisted address must authenticate
478             allowed = s_authenticate_curve (self, request, &metadata);
479         else
480         if (streq (request->mechanism, "GSSAPI"))
481             //  For GSSAPI, even a allowlisted address must authenticate
482             allowed = s_authenticate_gssapi (self, request);
483     }
484     if (allowed) {
485         size_t metasize = metadata - metabuf;
486         s_zap_request_reply (request, "200", "OK", metabuf, metasize);
487     } else
488         s_zap_request_reply (request, "400", "No access", (unsigned char *) "", 0);
489 
490     s_zap_request_destroy (&request);
491     free (metabuf);
492     return 0;
493 }
494 
495 
496 //  --------------------------------------------------------------------------
497 //  zauth() implements the zauth actor interface
498 
499 void
zauth(zsock_t * pipe,void * certstore)500 zauth (zsock_t *pipe, void *certstore)
501 {
502     self_t *self = s_self_new (pipe, (zcertstore_t *)certstore);
503     assert (self);
504 
505     //  Signal successful initialization
506     zsock_signal (pipe, 0);
507 
508     while (!self->terminated) {
509         zsock_t *which = (zsock_t *) zpoller_wait (self->poller, -1);
510         if (which == self->pipe)
511             s_self_handle_pipe (self);
512         else
513         if (which == self->handler)
514             s_self_authenticate (self);
515         else
516         if (zpoller_terminated (self->poller))
517             break;          //  Interrupted
518     }
519     s_self_destroy (&self);
520 }
521 
522 
523 //  --------------------------------------------------------------------------
524 //  Selftest
525 
526 #if (ZMQ_VERSION_MAJOR == 4)
527 //  Destroys old sockets and returns new ones
528 static void
s_renew_sockets(zsock_t ** server,zsock_t ** client)529 s_renew_sockets (zsock_t **server, zsock_t **client)
530 {
531     zsock_destroy (client);
532     zsock_destroy (server);
533     *server = zsock_new (ZMQ_PULL);
534     assert (*server);
535     *client = zsock_new (ZMQ_PUSH);
536     assert (*client);
537 }
538 
539 //  Checks whether client can connect to server
540 static bool
s_can_connect(zsock_t ** server,zsock_t ** client,bool renew)541 s_can_connect (zsock_t **server, zsock_t **client, bool renew)
542 {
543     int port_nbr = zsock_bind (*server, "tcp://127.0.0.1:*");
544     assert (port_nbr > 0);
545     int rc = zsock_connect (*client, "tcp://127.0.0.1:%d", port_nbr);
546     assert (rc == 0);
547     //  Give the connection time to fail if that's the plan
548     if (zsock_mechanism (*client) == ZMQ_CURVE)
549         zclock_sleep (1500);
550     else
551         zclock_sleep (200);
552 
553     //  By default PUSH sockets block if there's no peer
554     zsock_set_sndtimeo (*client, 200);
555     zstr_send (*client, "Hello, World");
556 
557     zpoller_t *poller = zpoller_new (*server, NULL);
558     assert (poller);
559     bool success = (zpoller_wait (poller, 400) == *server);
560     zpoller_destroy (&poller);
561 
562     if (renew == true)
563         s_renew_sockets (server, client);
564 
565     return success;
566 }
567 
568 static void
s_test_loader(zcertstore_t * certstore)569 s_test_loader (zcertstore_t *certstore)
570 {
571     zcertstore_empty (certstore);
572 
573     byte public_key [32] = { 105, 76, 150, 58, 214, 191, 218, 65, 50, 172,
574                              131, 188, 247, 211, 136, 170, 227, 26, 57, 170,
575                              185, 63, 246, 225, 177, 230, 12, 8, 134, 136,
576                              105, 106 };
577     byte secret_key [32] = { 245, 217, 172, 73, 106, 28, 195, 17, 218, 132,
578                              135, 209, 99, 240, 98, 232, 7, 137, 244, 100,
579                              242, 23, 29, 114, 70, 223, 83, 1, 113, 207,
580                              132, 149 };
581 
582     zcert_t *cert = zcert_new_from (public_key, secret_key);
583     assert (cert);
584     zcertstore_insert (certstore, &cert);
585 }
586 #endif
587 
588 void
zauth_test(bool verbose)589 zauth_test (bool verbose)
590 {
591     printf (" * zauth: ");
592 #if (ZMQ_VERSION_MAJOR == 4)
593     if (verbose)
594         printf ("\n");
595 
596     //  @selftest
597 
598     const char *SELFTEST_DIR_RW = "src/selftest-rw";
599 
600     const char *testbasedir  = ".test_zauth";
601     const char *testpassfile = "password-file";
602     const char *testcertfile = "mycert.txt";
603     char *basedirpath = NULL;   // subdir in a test, under SELFTEST_DIR_RW
604     char *passfilepath = NULL;  // pathname to testfile in a test, in dirpath
605     char *certfilepath = NULL;  // pathname to testfile in a test, in dirpath
606 
607     basedirpath = zsys_sprintf ("%s/%s", SELFTEST_DIR_RW, testbasedir);
608     assert (basedirpath);
609     passfilepath = zsys_sprintf ("%s/%s", basedirpath, testpassfile);
610     assert (passfilepath);
611     certfilepath = zsys_sprintf ("%s/%s", basedirpath, testcertfile);
612     assert (certfilepath);
613 
614     // Make sure old aborted tests do not hinder us
615     zdir_t *dir = zdir_new (basedirpath, NULL);
616     if (dir) {
617         zdir_remove (dir, true);
618         zdir_destroy (&dir);
619     }
620     zsys_file_delete (passfilepath);
621     zsys_file_delete (certfilepath);
622     zsys_dir_delete  (basedirpath);
623 
624     //  Create temporary directory for test files
625     zsys_dir_create (basedirpath);
626 
627     //  Check there's no authentication
628     zsock_t *server = zsock_new (ZMQ_PULL);
629     assert (server);
630     zsock_t *client = zsock_new (ZMQ_PUSH);
631     assert (client);
632     bool success = s_can_connect (&server, &client, true);
633     assert (success);
634 
635     //  Install the authenticator
636     zactor_t *auth = zactor_new (zauth, NULL);
637     assert (auth);
638     if (verbose) {
639         zstr_sendx (auth, "VERBOSE", NULL);
640         zsock_wait (auth);
641     }
642     //  Check there's no authentication on a default NULL server
643     success = s_can_connect (&server, &client, true);
644     assert (success);
645 
646     //  When we set a domain on the server, we switch on authentication
647     //  for NULL sockets, but with no policies, the client connection
648     //  will be allowed.
649     zsock_set_zap_domain (server, "global");
650     success = s_can_connect (&server, &client, true);
651     assert (success);
652 
653     //  Block 127.0.0.1, connection should fail
654     zsock_set_zap_domain (server, "global");
655     zstr_sendx (auth, "DENY", "127.0.0.1", NULL);
656     zsock_wait (auth);
657     success = s_can_connect (&server, &client, true);
658     assert (!success);
659 
660     //  Allow our address, which overrides the block list
661     zsock_set_zap_domain (server, "global");
662     zstr_sendx (auth, "ALLOW", "127.0.0.1", NULL);
663     zsock_wait (auth);
664     success = s_can_connect (&server, &client, true);
665     assert (success);
666 
667     //  Try PLAIN authentication
668     zsock_set_zap_domain (server, "global");
669     zsock_set_plain_server (server, 1);
670     zsock_set_plain_username (client, "admin");
671     zsock_set_plain_password (client, "Password");
672     success = s_can_connect (&server, &client, true);
673     assert (!success);
674 
675     FILE *password = fopen (passfilepath, "w");
676     assert (password);
677     fprintf (password, "admin=Password\n");
678     fclose (password);
679     zsock_set_zap_domain (server, "global");
680     zsock_set_plain_server (server, 1);
681     zsock_set_plain_username (client, "admin");
682     zsock_set_plain_password (client, "Password");
683     zstr_sendx (auth, "PLAIN", passfilepath, NULL);
684     zsock_wait (auth);
685     success = s_can_connect (&server, &client, false);
686     assert (success);
687 
688 #if (ZMQ_VERSION >= ZMQ_MAKE_VERSION (4, 1, 0))
689     // Test that the User-Id metadata is present
690     zframe_t *frame = zframe_recv (server);
691     assert (frame != NULL);
692     const char *user_id = zframe_meta (frame, "User-Id");
693     assert (user_id != NULL);
694     assert (streq (user_id, "admin"));
695     zframe_destroy (&frame);
696 #endif
697     s_renew_sockets(&server, &client);
698 
699     zsock_set_zap_domain (server, "global");
700     zsock_set_plain_server (server, 1);
701     zsock_set_plain_username (client, "admin");
702     zsock_set_plain_password (client, "Bogus");
703     success = s_can_connect (&server, &client, true);
704     assert (!success);
705 
706     if (zsys_has_curve ()) {
707         //  Try CURVE authentication
708         //  We'll create two new certificates and save the client public
709         //  certificate on disk; in a real case we'd transfer this securely
710         //  from the client machine to the server machine.
711         zcert_t *server_cert = zcert_new ();
712         assert (server_cert);
713         zcert_t *client_cert = zcert_new ();
714         assert (client_cert);
715         const char *server_key = zcert_public_txt (server_cert);
716 
717         //  Test without setting-up any authentication
718         zcert_apply (server_cert, server);
719         zcert_apply (client_cert, client);
720         zsock_set_curve_server (server, 1);
721         zsock_set_curve_serverkey (client, server_key);
722         zsock_set_zap_domain (server, "global");
723         success = s_can_connect (&server, &client, true);
724         assert (!success);
725 
726         //  Test CURVE_ALLOW_ANY
727         zcert_apply (server_cert, server);
728         zcert_apply (client_cert, client);
729         zsock_set_curve_server (server, 1);
730         zsock_set_curve_serverkey (client, server_key);
731         zstr_sendx (auth, "CURVE", CURVE_ALLOW_ANY, NULL);
732         zsock_wait (auth);
733         success = s_can_connect (&server, &client, true);
734         assert (success);
735 
736         //  Test full client authentication using certificates
737         zcert_set_meta (client_cert, "Hello", "%s", "World!");
738         zcert_apply (server_cert, server);
739         zcert_apply (client_cert, client);
740         zsock_set_curve_server (server, 1);
741         zsock_set_curve_serverkey (client, server_key);
742         zcert_save_public (client_cert, certfilepath);
743         zstr_sendx (auth, "CURVE", basedirpath, NULL);
744         zsock_wait (auth);
745         zsock_set_zap_domain (server, "global");
746         success = s_can_connect (&server, &client, false);
747         assert (success);
748 
749 #if (ZMQ_VERSION >= ZMQ_MAKE_VERSION (4, 1, 0))
750         // Test send/recv certificate metadata
751         zframe_t *frame = zframe_recv (server);
752         assert (frame != NULL);
753         const char *meta = zframe_meta (frame, "Hello");
754         assert (meta != NULL);
755         assert (streq (meta, "World!"));
756         const char *user_id = zframe_meta (frame, "User-Id");
757         assert (user_id != NULL);
758         assert (streq (user_id, zcert_public_txt(client_cert)));
759         zframe_destroy (&frame);
760         s_renew_sockets(&server, &client);
761 #endif
762 
763         zcert_destroy (&server_cert);
764         zcert_destroy (&client_cert);
765 
766         // Test custom zcertstore
767         zcertstore_t *certstore = zcertstore_new (NULL);
768         zcertstore_set_loader (certstore, s_test_loader, NULL, NULL);
769         zactor_destroy(&auth);
770         auth = zactor_new (zauth, certstore);
771         assert (auth);
772         if (verbose) {
773             zstr_sendx (auth, "VERBOSE", NULL);
774             zsock_wait (auth);
775         }
776 
777         byte public_key [32] = { 105, 76, 150, 58, 214, 191, 218, 65, 50, 172,
778                                  131, 188, 247, 211, 136, 170, 227, 26, 57, 170,
779                                  185, 63, 246, 225, 177, 230, 12, 8, 134, 136,
780                                  105, 106 };
781         byte secret_key [32] = { 245, 217, 172, 73, 106, 28, 195, 17, 218, 132,
782                                  135, 209, 99, 240, 98, 232, 7, 137, 244, 100,
783                                  242, 23, 29, 114, 70, 223, 83, 1, 113, 207,
784                                  132, 149 };
785         zcert_t *shared_cert = zcert_new_from (public_key, secret_key);
786         assert (shared_cert);
787         zcert_apply (shared_cert, server);
788         zcert_apply (shared_cert, client);
789         zsock_set_curve_server (server, 1);
790         zsock_set_curve_serverkey (client, "x?T*N/1Y{8goubv{Ts}#&#f}TXJ//DVe#D2HkoLU");
791         success = s_can_connect (&server, &client, true);
792         assert (success);
793         zcert_destroy (&shared_cert);
794     }
795     //  Remove the authenticator and check a normal connection works
796     zactor_destroy (&auth);
797     success = s_can_connect (&server, &client, true);
798     assert (success);
799 
800     zsock_destroy (&client);
801     zsock_destroy (&server);
802 
803     //  Delete all test files
804     dir = zdir_new (basedirpath, NULL);
805     assert (dir);
806     zdir_remove (dir, true);
807     zdir_destroy (&dir);
808 
809     zstr_free (&passfilepath);
810     zstr_free (&certfilepath);
811     zstr_free (&basedirpath);
812 
813 #endif
814 
815 #if defined (__WINDOWS__)
816     zsys_shutdown();
817 #endif
818 
819     //  @end
820     printf ("OK\n");
821 }
822