Line data Source code
1 : /*
2 : Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
3 :
4 : This file is part of libzmq, the ZeroMQ core engine in C++.
5 :
6 : libzmq is free software; you can redistribute it and/or modify it under
7 : the terms of the GNU Lesser General Public License (LGPL) as published
8 : by the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : As a special exception, the Contributors give you permission to link
12 : this library with independent modules to produce an executable,
13 : regardless of the license terms of these independent modules, and to
14 : copy and distribute the resulting executable under terms of your choice,
15 : provided that you also meet, for each linked independent module, the
16 : terms and conditions of the license of that module. An independent
17 : module is a module which is not derived from or based on this library.
18 : If you modify this library, you must extend this exception to your
19 : version of the library.
20 :
21 : libzmq is distributed in the hope that it will be useful, but WITHOUT
22 : ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
24 : License for more details.
25 :
26 : You should have received a copy of the GNU Lesser General Public License
27 : along with this program. If not, see <http://www.gnu.org/licenses/>.
28 : */
29 :
30 : #include "precompiled.hpp"
31 : #include "platform.hpp"
32 : #ifdef ZMQ_HAVE_WINDOWS
33 : #include "windows.hpp"
34 : #endif
35 :
36 : #include <stddef.h>
37 : #include <string.h>
38 : #include <stdlib.h>
39 :
40 : #include "err.hpp"
41 : #include "msg.hpp"
42 : #include "session_base.hpp"
43 : #include "wire.hpp"
44 : #include "null_mechanism.hpp"
45 :
46 4209 : zmq::null_mechanism_t::null_mechanism_t (session_base_t *session_,
47 : const std::string &peer_address_,
48 : const options_t &options_) :
49 : mechanism_t (options_),
50 : session (session_),
51 : peer_address (peer_address_),
52 : ready_command_sent (false),
53 : error_command_sent (false),
54 : ready_command_received (false),
55 : error_command_received (false),
56 : zap_connected (false),
57 : zap_request_sent (false),
58 4209 : zap_reply_received (false)
59 : {
60 : // NULL mechanism only uses ZAP if there's a domain defined
61 : // This prevents ZAP requests on naive sockets
62 8418 : if (options.zap_domain.size () > 0
63 4209 : && session->zap_connect () == 0)
64 9 : zap_connected = true;
65 4209 : }
66 :
67 12627 : zmq::null_mechanism_t::~null_mechanism_t ()
68 : {
69 8418 : }
70 :
71 8826 : int zmq::null_mechanism_t::next_handshake_command (msg_t *msg_)
72 : {
73 8826 : if (ready_command_sent || error_command_sent) {
74 4787 : errno = EAGAIN;
75 4787 : return -1;
76 : }
77 4039 : if (zap_connected && !zap_reply_received) {
78 18 : if (zap_request_sent) {
79 9 : errno = EAGAIN;
80 9 : return -1;
81 : }
82 9 : send_zap_request ();
83 9 : zap_request_sent = true;
84 9 : const int rc = receive_and_process_zap_reply ();
85 9 : if (rc != 0)
86 : return -1;
87 0 : zap_reply_received = true;
88 : }
89 :
90 4021 : if (zap_reply_received
91 9 : && strncmp (status_code, "200", sizeof status_code) != 0) {
92 3 : const int rc = msg_->init_size (6 + 1 + sizeof status_code);
93 3 : zmq_assert (rc == 0);
94 : unsigned char *msg_data =
95 3 : static_cast <unsigned char *> (msg_->data ());
96 : memcpy (msg_data, "\5ERROR", 6);
97 3 : msg_data [6] = sizeof status_code;
98 3 : memcpy (msg_data + 7, status_code, sizeof status_code);
99 3 : error_command_sent = true;
100 3 : return 0;
101 : }
102 :
103 4018 : unsigned char *const command_buffer = (unsigned char *) malloc (512);
104 4018 : alloc_assert (command_buffer);
105 :
106 4018 : unsigned char *ptr = command_buffer;
107 :
108 : // Add mechanism string
109 : memcpy (ptr, "\5READY", 6);
110 4018 : ptr += 6;
111 :
112 : // Add socket type property
113 4018 : const char *socket_type = socket_type_string (options.type);
114 4018 : ptr += add_property (ptr, "Socket-Type", socket_type, strlen (socket_type));
115 :
116 : // Add identity property
117 4018 : if (options.type == ZMQ_REQ
118 4018 : || options.type == ZMQ_DEALER
119 4018 : || options.type == ZMQ_ROUTER)
120 957 : ptr += add_property (ptr, "Identity", options.identity, options.identity_size);
121 :
122 4018 : const size_t command_size = ptr - command_buffer;
123 4018 : const int rc = msg_->init_size (command_size);
124 4018 : errno_assert (rc == 0);
125 4018 : memcpy (msg_->data (), command_buffer, command_size);
126 4018 : free (command_buffer);
127 :
128 4018 : ready_command_sent = true;
129 :
130 4018 : return 0;
131 : }
132 :
133 3864 : int zmq::null_mechanism_t::process_handshake_command (msg_t *msg_)
134 : {
135 3864 : if (ready_command_received || error_command_received) {
136 : // Temporary support for security debugging
137 0 : puts ("NULL I: client sent invalid NULL handshake (duplicate READY)");
138 0 : errno = EPROTO;
139 0 : return -1;
140 : }
141 :
142 : const unsigned char *cmd_data =
143 3864 : static_cast <unsigned char *> (msg_->data ());
144 3864 : const size_t data_size = msg_->size ();
145 :
146 3864 : int rc = 0;
147 3864 : if (data_size >= 6 && !memcmp (cmd_data, "\5READY", 6))
148 3860 : rc = process_ready_command (cmd_data, data_size);
149 : else
150 4 : if (data_size >= 6 && !memcmp (cmd_data, "\5ERROR", 6))
151 3 : rc = process_error_command (cmd_data, data_size);
152 : else {
153 : // Temporary support for security debugging
154 1 : puts ("NULL I: client sent invalid NULL handshake (not READY)");
155 0 : errno = EPROTO;
156 0 : rc = -1;
157 : }
158 :
159 3864 : if (rc == 0) {
160 3864 : rc = msg_->close ();
161 3864 : errno_assert (rc == 0);
162 3864 : rc = msg_->init ();
163 3864 : errno_assert (rc == 0);
164 : }
165 3864 : return rc;
166 : }
167 :
168 0 : int zmq::null_mechanism_t::process_ready_command (
169 : const unsigned char *cmd_data, size_t data_size)
170 : {
171 3860 : ready_command_received = true;
172 3860 : return parse_metadata (cmd_data + 6, data_size - 6);
173 : }
174 :
175 3 : int zmq::null_mechanism_t::process_error_command (
176 : const unsigned char *cmd_data, size_t data_size)
177 : {
178 3 : if (data_size < 7) {
179 0 : errno = EPROTO;
180 0 : return -1;
181 : }
182 3 : const size_t error_reason_len = static_cast <size_t> (cmd_data [6]);
183 3 : if (error_reason_len > data_size - 7) {
184 0 : errno = EPROTO;
185 0 : return -1;
186 : }
187 3 : error_command_received = true;
188 3 : return 0;
189 : }
190 :
191 9 : int zmq::null_mechanism_t::zap_msg_available ()
192 : {
193 9 : if (zap_reply_received) {
194 0 : errno = EFSM;
195 0 : return -1;
196 : }
197 9 : const int rc = receive_and_process_zap_reply ();
198 9 : if (rc == 0)
199 9 : zap_reply_received = true;
200 9 : return rc;
201 : }
202 :
203 24770 : zmq::mechanism_t::status_t zmq::null_mechanism_t::status () const
204 : {
205 : const bool command_sent =
206 24770 : ready_command_sent || error_command_sent;
207 : const bool command_received =
208 24770 : ready_command_received || error_command_received;
209 :
210 24770 : if (ready_command_sent && ready_command_received)
211 : return ready;
212 : else
213 21024 : if (command_sent && command_received)
214 : return error;
215 : else
216 21006 : return handshaking;
217 : }
218 :
219 9 : void zmq::null_mechanism_t::send_zap_request ()
220 : {
221 : int rc;
222 : msg_t msg;
223 :
224 : // Address delimiter frame
225 9 : rc = msg.init ();
226 9 : errno_assert (rc == 0);
227 9 : msg.set_flags (msg_t::more);
228 9 : rc = session->write_zap_msg (&msg);
229 9 : errno_assert (rc == 0);
230 :
231 : // Version frame
232 9 : rc = msg.init_size (3);
233 9 : errno_assert (rc == 0);
234 9 : memcpy (msg.data (), "1.0", 3);
235 9 : msg.set_flags (msg_t::more);
236 9 : rc = session->write_zap_msg (&msg);
237 9 : errno_assert (rc == 0);
238 :
239 : // Request id frame
240 9 : rc = msg.init_size (1);
241 9 : errno_assert (rc == 0);
242 9 : memcpy (msg.data (), "1", 1);
243 9 : msg.set_flags (msg_t::more);
244 9 : rc = session->write_zap_msg (&msg);
245 9 : errno_assert (rc == 0);
246 :
247 : // Domain frame
248 18 : rc = msg.init_size (options.zap_domain.length ());
249 9 : errno_assert (rc == 0);
250 18 : memcpy (msg.data (), options.zap_domain.c_str (), options.zap_domain.length ());
251 9 : msg.set_flags (msg_t::more);
252 9 : rc = session->write_zap_msg (&msg);
253 9 : errno_assert (rc == 0);
254 :
255 : // Address frame
256 18 : rc = msg.init_size (peer_address.length ());
257 9 : errno_assert (rc == 0);
258 18 : memcpy (msg.data (), peer_address.c_str (), peer_address.length ());
259 9 : msg.set_flags (msg_t::more);
260 9 : rc = session->write_zap_msg (&msg);
261 9 : errno_assert (rc == 0);
262 :
263 : // Identity frame
264 9 : rc = msg.init_size (options.identity_size);
265 9 : errno_assert (rc == 0);
266 9 : memcpy (msg.data (), options.identity, options.identity_size);
267 9 : msg.set_flags (msg_t::more);
268 9 : rc = session->write_zap_msg (&msg);
269 9 : errno_assert (rc == 0);
270 :
271 : // Mechanism frame
272 9 : rc = msg.init_size (4);
273 9 : errno_assert (rc == 0);
274 9 : memcpy (msg.data (), "NULL", 4);
275 9 : rc = session->write_zap_msg (&msg);
276 9 : errno_assert (rc == 0);
277 9 : }
278 :
279 18 : int zmq::null_mechanism_t::receive_and_process_zap_reply ()
280 : {
281 18 : int rc = 0;
282 : msg_t msg [7]; // ZAP reply consists of 7 frames
283 :
284 : // Initialize all reply frames
285 144 : for (int i = 0; i < 7; i++) {
286 126 : rc = msg [i].init ();
287 126 : errno_assert (rc == 0);
288 : }
289 :
290 63 : for (int i = 0; i < 7; i++) {
291 72 : rc = session->read_zap_msg (&msg [i]);
292 72 : if (rc == -1)
293 : break;
294 63 : if ((msg [i].flags () & msg_t::more) == (i < 6? 0: msg_t::more)) {
295 : // Temporary support for security debugging
296 0 : puts ("NULL I: ZAP handler sent incomplete reply message");
297 0 : errno = EPROTO;
298 0 : rc = -1;
299 0 : break;
300 : }
301 : }
302 :
303 18 : if (rc != 0)
304 : goto error;
305 :
306 : // Address delimiter frame
307 9 : if (msg [0].size () > 0) {
308 : // Temporary support for security debugging
309 0 : puts ("NULL I: ZAP handler sent malformed reply message");
310 0 : errno = EPROTO;
311 0 : rc = -1;
312 0 : goto error;
313 : }
314 :
315 : // Version frame
316 9 : if (msg [1].size () != 3 || memcmp (msg [1].data (), "1.0", 3)) {
317 : // Temporary support for security debugging
318 0 : puts ("NULL I: ZAP handler sent bad version number");
319 0 : errno = EPROTO;
320 0 : rc = -1;
321 0 : goto error;
322 : }
323 :
324 : // Request id frame
325 9 : if (msg [2].size () != 1 || memcmp (msg [2].data (), "1", 1)) {
326 : // Temporary support for security debugging
327 0 : puts ("NULL I: ZAP handler sent bad request ID");
328 0 : errno = EPROTO;
329 0 : rc = -1;
330 0 : goto error;
331 : }
332 :
333 : // Status code frame
334 9 : if (msg [3].size () != 3) {
335 : // Temporary support for security debugging
336 0 : puts ("NULL I: ZAP handler rejected client authentication");
337 0 : errno = EPROTO;
338 0 : rc = -1;
339 0 : goto error;
340 : }
341 :
342 : // Save status code
343 9 : memcpy (status_code, msg [3].data (), sizeof status_code);
344 :
345 : // Save user id
346 9 : set_user_id (msg [5].data (), msg [5].size ());
347 :
348 : // Process metadata frame
349 9 : rc = parse_metadata (static_cast <const unsigned char*> (msg [6].data ()),
350 18 : msg [6].size (), true);
351 :
352 : error:
353 144 : for (int i = 0; i < 7; i++) {
354 126 : const int rc2 = msg [i].close ();
355 126 : errno_assert (rc2 == 0);
356 : }
357 :
358 18 : return rc;
359 : }
|