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