1ZAUTH(3) CZMQ Manual ZAUTH(3)
2
3
4
6 zauth - Class for authentication for ZeroMQ security mechanisms
7
9 #define CURVE_ALLOW_ANY "*"
10
11 // CZMQ v3 API (for use with zsock, not zsocket, which is deprecated).
12 //
13 // Create new zauth actor instance. This installs authentication on all
14 // zsock sockets. Until you add policies, all incoming NULL connections are
15 // allowed (classic ZeroMQ behaviour), and all PLAIN and CURVE connections
16 // are denied:
17 //
18 // zactor_t *auth = zactor_new (zauth, NULL);
19 //
20 // Destroy zauth instance. This removes authentication and allows all
21 // connections to pass, without authentication:
22 //
23 // zactor_destroy (&auth);
24 //
25 // Note that all zauth commands are synchronous, so your application always
26 // waits for a signal from the actor after each command.
27 //
28 // Enable verbose logging of commands and activity. Verbose logging can help
29 // debug non-trivial authentication policies:
30 //
31 // zstr_send (auth, "VERBOSE");
32 // zsock_wait (auth);
33 //
34 // Allow a list of IP addresses. For NULL, all clients from
35 // these addresses will be accepted. For PLAIN and CURVE, they will be
36 // allowed to continue with authentication. You can call this method
37 // multiple times to allow more IP addresses. If you allow one
38 // or more addresses, any non-allowed addresses are treated as
39 // blocked:
40 //
41 // zstr_sendx (auth, "ALLOW", "127.0.0.1", "127.0.0.2", NULL);
42 // zsock_wait (auth);
43 //
44 // Deny (block) a list of IP addresses. For all security mechanisms,
45 // this rejects the connection without any further authentication. Use
46 // either an allowed list, or a blocked list, not not both. If you define both
47 // an allowed list and a blocked list, only the allowed list takes effect:
48 //
49 // zstr_sendx (auth, "DENY", "192.168.0.1", "192.168.0.2", NULL);
50 // zsock_wait (auth);
51 //
52 // Configure PLAIN authentication using a plain-text password file. You can
53 // modify the password file at any time; zauth will reload it automatically
54 // if modified externally:
55 //
56 // zstr_sendx (auth, "PLAIN", filename, NULL);
57 // zsock_wait (auth);
58 //
59 // Configure CURVE authentication, using a directory that holds all public
60 // client certificates, i.e. their public keys. The certificates must be in
61 // zcert_save format. You can add and remove certificates in that directory
62 // at any time. To allow all client keys without checking, specify
63 // CURVE_ALLOW_ANY for the directory name:
64 //
65 // zstr_sendx (auth, "CURVE", directory, NULL);
66 // zsock_wait (auth);
67 //
68 // Configure GSSAPI authentication, using an underlying mechanism (usually
69 // Kerberos) to establish a secure context and perform mutual authentication:
70 //
71 // zstr_sendx (auth, "GSSAPI", NULL);
72 // zsock_wait (auth);
73 //
74 // This is the zauth constructor as a zactor_fn:
75 CZMQ_EXPORT void
76 zauth (zsock_t *pipe, void *certstore);
77
78 // Selftest
79 CZMQ_EXPORT void
80 zauth_test (bool verbose);
81 Please add '@interface' section in './../src/zauth.c'.
82
84 A zauth actor takes over authentication for all incoming connections in
85 its context. You can allow or block peers based on IP address, and
86 define policies for securing PLAIN, CURVE, and GSSAPI connections.
87
88 This class replaces zauth_v2, and is meant for applications that use
89 the CZMQ v3 API (meaning, zsock).
90
92 From zauth_test method.
93
94 const char *SELFTEST_DIR_RW = "src/selftest-rw";
95
96 const char *testbasedir = ".test_zauth";
97 const char *testpassfile = "password-file";
98 const char *testcertfile = "mycert.txt";
99 char *basedirpath = NULL; // subdir in a test, under SELFTEST_DIR_RW
100 char *passfilepath = NULL; // pathname to testfile in a test, in dirpath
101 char *certfilepath = NULL; // pathname to testfile in a test, in dirpath
102
103 basedirpath = zsys_sprintf ("%s/%s", SELFTEST_DIR_RW, testbasedir);
104 assert (basedirpath);
105 passfilepath = zsys_sprintf ("%s/%s", basedirpath, testpassfile);
106 assert (passfilepath);
107 certfilepath = zsys_sprintf ("%s/%s", basedirpath, testcertfile);
108 assert (certfilepath);
109
110 // Make sure old aborted tests do not hinder us
111 zdir_t *dir = zdir_new (basedirpath, NULL);
112 if (dir) {
113 zdir_remove (dir, true);
114 zdir_destroy (&dir);
115 }
116 zsys_file_delete (passfilepath);
117 zsys_file_delete (certfilepath);
118 zsys_dir_delete (basedirpath);
119
120 // Create temporary directory for test files
121 zsys_dir_create (basedirpath);
122
123 // Check there's no authentication
124 zsock_t *server = zsock_new (ZMQ_PULL);
125 assert (server);
126 zsock_t *client = zsock_new (ZMQ_PUSH);
127 assert (client);
128 bool success = s_can_connect (&server, &client, true);
129 assert (success);
130
131 // Install the authenticator
132 zactor_t *auth = zactor_new (zauth, NULL);
133 assert (auth);
134 if (verbose) {
135 zstr_sendx (auth, "VERBOSE", NULL);
136 zsock_wait (auth);
137 }
138 // Check there's no authentication on a default NULL server
139 success = s_can_connect (&server, &client, true);
140 assert (success);
141
142 // When we set a domain on the server, we switch on authentication
143 // for NULL sockets, but with no policies, the client connection
144 // will be allowed.
145 zsock_set_zap_domain (server, "global");
146 success = s_can_connect (&server, &client, true);
147 assert (success);
148
149 // Block 127.0.0.1, connection should fail
150 zsock_set_zap_domain (server, "global");
151 zstr_sendx (auth, "DENY", "127.0.0.1", NULL);
152 zsock_wait (auth);
153 success = s_can_connect (&server, &client, true);
154 assert (!success);
155
156 // Allow our address, which overrides the block list
157 zsock_set_zap_domain (server, "global");
158 zstr_sendx (auth, "ALLOW", "127.0.0.1", NULL);
159 zsock_wait (auth);
160 success = s_can_connect (&server, &client, true);
161 assert (success);
162
163 // Try PLAIN authentication
164 zsock_set_zap_domain (server, "global");
165 zsock_set_plain_server (server, 1);
166 zsock_set_plain_username (client, "admin");
167 zsock_set_plain_password (client, "Password");
168 success = s_can_connect (&server, &client, true);
169 assert (!success);
170
171 FILE *password = fopen (passfilepath, "w");
172 assert (password);
173 fprintf (password, "admin=Password\n");
174 fclose (password);
175 zsock_set_zap_domain (server, "global");
176 zsock_set_plain_server (server, 1);
177 zsock_set_plain_username (client, "admin");
178 zsock_set_plain_password (client, "Password");
179 zstr_sendx (auth, "PLAIN", passfilepath, NULL);
180 zsock_wait (auth);
181 success = s_can_connect (&server, &client, false);
182 assert (success);
183
184 #if (ZMQ_VERSION >= ZMQ_MAKE_VERSION (4, 1, 0))
185 // Test that the User-Id metadata is present
186 zframe_t *frame = zframe_recv (server);
187 assert (frame != NULL);
188 const char *user_id = zframe_meta (frame, "User-Id");
189 assert (user_id != NULL);
190 assert (streq (user_id, "admin"));
191 zframe_destroy (&frame);
192 #endif
193 s_renew_sockets(&server, &client);
194
195 zsock_set_zap_domain (server, "global");
196 zsock_set_plain_server (server, 1);
197 zsock_set_plain_username (client, "admin");
198 zsock_set_plain_password (client, "Bogus");
199 success = s_can_connect (&server, &client, true);
200 assert (!success);
201
202 if (zsys_has_curve ()) {
203 // Try CURVE authentication
204 // We'll create two new certificates and save the client public
205 // certificate on disk; in a real case we'd transfer this securely
206 // from the client machine to the server machine.
207 zcert_t *server_cert = zcert_new ();
208 assert (server_cert);
209 zcert_t *client_cert = zcert_new ();
210 assert (client_cert);
211 const char *server_key = zcert_public_txt (server_cert);
212
213 // Test without setting-up any authentication
214 zcert_apply (server_cert, server);
215 zcert_apply (client_cert, client);
216 zsock_set_curve_server (server, 1);
217 zsock_set_curve_serverkey (client, server_key);
218 zsock_set_zap_domain (server, "global");
219 success = s_can_connect (&server, &client, true);
220 assert (!success);
221
222 // Test CURVE_ALLOW_ANY
223 zcert_apply (server_cert, server);
224 zcert_apply (client_cert, client);
225 zsock_set_curve_server (server, 1);
226 zsock_set_curve_serverkey (client, server_key);
227 zstr_sendx (auth, "CURVE", CURVE_ALLOW_ANY, NULL);
228 zsock_wait (auth);
229 success = s_can_connect (&server, &client, true);
230 assert (success);
231
232 // Test full client authentication using certificates
233 zcert_set_meta (client_cert, "Hello", "%s", "World!");
234 zcert_apply (server_cert, server);
235 zcert_apply (client_cert, client);
236 zsock_set_curve_server (server, 1);
237 zsock_set_curve_serverkey (client, server_key);
238 zcert_save_public (client_cert, certfilepath);
239 zstr_sendx (auth, "CURVE", basedirpath, NULL);
240 zsock_wait (auth);
241 zsock_set_zap_domain (server, "global");
242 success = s_can_connect (&server, &client, false);
243 assert (success);
244
245 #if (ZMQ_VERSION >= ZMQ_MAKE_VERSION (4, 1, 0))
246 // Test send/recv certificate metadata
247 zframe_t *frame = zframe_recv (server);
248 assert (frame != NULL);
249 const char *meta = zframe_meta (frame, "Hello");
250 assert (meta != NULL);
251 assert (streq (meta, "World!"));
252 const char *user_id = zframe_meta (frame, "User-Id");
253 assert (user_id != NULL);
254 assert (streq (user_id, zcert_public_txt(client_cert)));
255 zframe_destroy (&frame);
256 s_renew_sockets(&server, &client);
257 #endif
258
259 zcert_destroy (&server_cert);
260 zcert_destroy (&client_cert);
261
262 // Test custom zcertstore
263 zcertstore_t *certstore = zcertstore_new (NULL);
264 zcertstore_set_loader (certstore, s_test_loader, NULL, NULL);
265 zactor_destroy(&auth);
266 auth = zactor_new (zauth, certstore);
267 assert (auth);
268 if (verbose) {
269 zstr_sendx (auth, "VERBOSE", NULL);
270 zsock_wait (auth);
271 }
272
273 byte public_key [32] = { 105, 76, 150, 58, 214, 191, 218, 65, 50, 172,
274 131, 188, 247, 211, 136, 170, 227, 26, 57, 170,
275 185, 63, 246, 225, 177, 230, 12, 8, 134, 136,
276 105, 106 };
277 byte secret_key [32] = { 245, 217, 172, 73, 106, 28, 195, 17, 218, 132,
278 135, 209, 99, 240, 98, 232, 7, 137, 244, 100,
279 242, 23, 29, 114, 70, 223, 83, 1, 113, 207,
280 132, 149 };
281 zcert_t *shared_cert = zcert_new_from (public_key, secret_key);
282 assert (shared_cert);
283 zcert_apply (shared_cert, server);
284 zcert_apply (shared_cert, client);
285 zsock_set_curve_server (server, 1);
286 zsock_set_curve_serverkey (client, "x?T*N/1Y{8goubv{Ts}#&#f}TXJ//DVe#D2HkoLU");
287 success = s_can_connect (&server, &client, true);
288 assert (success);
289 zcert_destroy (&shared_cert);
290 }
291 // Remove the authenticator and check a normal connection works
292 zactor_destroy (&auth);
293 success = s_can_connect (&server, &client, true);
294 assert (success);
295
296 zsock_destroy (&client);
297 zsock_destroy (&server);
298
299 // Delete all test files
300 dir = zdir_new (basedirpath, NULL);
301 assert (dir);
302 zdir_remove (dir, true);
303 zdir_destroy (&dir);
304
305 zstr_free (&passfilepath);
306 zstr_free (&certfilepath);
307 zstr_free (&basedirpath);
308
309 #endif
310
311 #if defined (__WINDOWS__)
312 zsys_shutdown();
313 #endif
314
315
317 The czmq manual was written by the authors in the AUTHORS file.
318
320 Main web site:
321
322 Report bugs to the email <zeromq-dev@lists.zeromq.org[1]>
323
325 Copyright (c) the Contributors as noted in the AUTHORS file. This file
326 is part of CZMQ, the high-level C binding for 0MQ:
327 http://czmq.zeromq.org. This Source Code Form is subject to the terms
328 of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
329 distributed with this file, You can obtain one at
330 http://mozilla.org/MPL/2.0/. LICENSE included with the czmq
331 distribution.
332
334 1. zeromq-dev@lists.zeromq.org
335 mailto:zeromq-dev@lists.zeromq.org
336
337
338
339CZMQ 4.2.1 02/01/2021 ZAUTH(3)