libzmq  master
ZeroMQ C++ Core Engine (LIBZMQ)
plain_server.cpp
Go to the documentation of this file.
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 <string>
37 
38 #include "msg.hpp"
39 #include "session_base.hpp"
40 #include "err.hpp"
41 #include "plain_server.hpp"
42 #include "wire.hpp"
43 
45  const std::string &peer_address_,
46  const options_t &options_) :
47  mechanism_t (options_),
48  session (session_),
49  peer_address (peer_address_),
50  state (waiting_for_hello)
51 {
52 }
53 
55 {
56 }
57 
59 {
60  int rc = 0;
61 
62  switch (state) {
63  case sending_welcome:
64  rc = produce_welcome (msg_);
65  if (rc == 0)
67  break;
68  case sending_ready:
69  rc = produce_ready (msg_);
70  if (rc == 0)
71  state = ready;
72  break;
73  case sending_error:
74  rc = produce_error (msg_);
75  if (rc == 0)
77  break;
78  default:
79  errno = EAGAIN;
80  rc = -1;
81  }
82  return rc;
83 }
84 
86 {
87  int rc = 0;
88 
89  switch (state) {
90  case waiting_for_hello:
91  rc = process_hello (msg_);
92  break;
94  rc = process_initiate (msg_);
95  break;
96  default:
97  // Temporary support for security debugging
98  puts ("PLAIN I: invalid handshake command");
99  errno = EPROTO;
100  rc = -1;
101  break;
102  }
103  if (rc == 0) {
104  rc = msg_->close ();
105  errno_assert (rc == 0);
106  rc = msg_->init ();
107  errno_assert (rc == 0);
108  }
109  return rc;
110 }
111 
113 {
114  if (state == ready)
115  return mechanism_t::ready;
116  else
117  if (state == error_command_sent)
118  return mechanism_t::error;
119  else
121 }
122 
124 {
125  if (state != waiting_for_zap_reply) {
126  errno = EFSM;
127  return -1;
128  }
129  const int rc = receive_and_process_zap_reply ();
130  if (rc == 0)
131  state = status_code == "200"
133  : sending_error;
134  return rc;
135 }
136 
138 {
139  const unsigned char *ptr = static_cast <unsigned char *> (msg_->data ());
140  size_t bytes_left = msg_->size ();
141 
142  if (bytes_left < 6 || memcmp (ptr, "\x05HELLO", 6)) {
143  // Temporary support for security debugging
144  puts ("PLAIN I: invalid PLAIN client, did not send HELLO");
145  errno = EPROTO;
146  return -1;
147  }
148  ptr += 6;
149  bytes_left -= 6;
150 
151  if (bytes_left < 1) {
152  // Temporary support for security debugging
153  puts ("PLAIN I: invalid PLAIN client, did not send username");
154  errno = EPROTO;
155  return -1;
156  }
157  const size_t username_length = static_cast <size_t> (*ptr++);
158  bytes_left -= 1;
159 
160  if (bytes_left < username_length) {
161  // Temporary support for security debugging
162  puts ("PLAIN I: invalid PLAIN client, sent malformed username");
163  errno = EPROTO;
164  return -1;
165  }
166  const std::string username = std::string ((char *) ptr, username_length);
167  ptr += username_length;
168  bytes_left -= username_length;
169  if (bytes_left < 1) {
170  // Temporary support for security debugging
171  puts ("PLAIN I: invalid PLAIN client, did not send password");
172  errno = EPROTO;
173  return -1;
174  }
175 
176  const size_t password_length = static_cast <size_t> (*ptr++);
177  bytes_left -= 1;
178  if (bytes_left < password_length) {
179  // Temporary support for security debugging
180  puts ("PLAIN I: invalid PLAIN client, sent malformed password");
181  errno = EPROTO;
182  return -1;
183  }
184 
185  const std::string password = std::string ((char *) ptr, password_length);
186  ptr += password_length;
187  bytes_left -= password_length;
188  if (bytes_left > 0) {
189  // Temporary support for security debugging
190  puts ("PLAIN I: invalid PLAIN client, sent extraneous data");
191  errno = EPROTO;
192  return -1;
193  }
194 
195  // Use ZAP protocol (RFC 27) to authenticate the user.
196  int rc = session->zap_connect ();
197  if (rc == 0) {
198  send_zap_request (username, password);
200  if (rc == 0)
201  state = status_code == "200"
203  : sending_error;
204  else
205  if (errno == EAGAIN)
207  else
208  return -1;
209  }
210  else
212 
213  return 0;
214 }
215 
217 {
218  const int rc = msg_->init_size (8);
219  errno_assert (rc == 0);
220  memcpy (msg_->data (), "\x07WELCOME", 8);
221  return 0;
222 }
223 
225 {
226  const unsigned char *ptr = static_cast <unsigned char *> (msg_->data ());
227  const size_t bytes_left = msg_->size ();
228 
229  if (bytes_left < 9 || memcmp (ptr, "\x08INITIATE", 9)) {
230  // Temporary support for security debugging
231  puts ("PLAIN I: invalid PLAIN client, did not send INITIATE");
232  errno = EPROTO;
233  return -1;
234  }
235  const int rc = parse_metadata (ptr + 9, bytes_left - 9);
236  if (rc == 0)
238  return rc;
239 }
240 
242 {
243  unsigned char * const command_buffer = (unsigned char *) malloc (512);
244  alloc_assert (command_buffer);
245 
246  unsigned char *ptr = command_buffer;
247 
248  // Add command name
249  memcpy (ptr, "\x05READY", 6);
250  ptr += 6;
251 
252  // Add socket type property
253  const char *socket_type = socket_type_string (options.type);
254  ptr += add_property (ptr, "Socket-Type", socket_type, strlen (socket_type));
255 
256  // Add identity property
257  if (options.type == ZMQ_REQ
258  || options.type == ZMQ_DEALER
259  || options.type == ZMQ_ROUTER)
260  ptr += add_property (
261  ptr, "Identity", options.identity, options.identity_size);
262 
263  const size_t command_size = ptr - command_buffer;
264  const int rc = msg_->init_size (command_size);
265  errno_assert (rc == 0);
266  memcpy (msg_->data (), command_buffer, command_size);
267  free (command_buffer);
268 
269  return 0;
270 }
271 
273 {
274  zmq_assert (status_code.length () == 3);
275  const int rc = msg_->init_size (6 + 1 + status_code.length ());
276  zmq_assert (rc == 0);
277  char *msg_data = static_cast <char *> (msg_->data ());
278  memcpy (msg_data, "\5ERROR", 6);
279  msg_data [6] = (char) status_code.length ();
280  memcpy (msg_data + 7, status_code.c_str (), status_code.length ());
281  return 0;
282 }
283 
284 void zmq::plain_server_t::send_zap_request (const std::string &username,
285  const std::string &password)
286 {
287  int rc;
288  msg_t msg;
289 
290  // Address delimiter frame
291  rc = msg.init ();
292  errno_assert (rc == 0);
293  msg.set_flags (msg_t::more);
294  rc = session->write_zap_msg (&msg);
295  errno_assert (rc == 0);
296 
297  // Version frame
298  rc = msg.init_size (3);
299  errno_assert (rc == 0);
300  memcpy (msg.data (), "1.0", 3);
301  msg.set_flags (msg_t::more);
302  rc = session->write_zap_msg (&msg);
303  errno_assert (rc == 0);
304 
305  // Request id frame
306  rc = msg.init_size (1);
307  errno_assert (rc == 0);
308  memcpy (msg.data (), "1", 1);
309  msg.set_flags (msg_t::more);
310  rc = session->write_zap_msg (&msg);
311  errno_assert (rc == 0);
312 
313  // Domain frame
314  rc = msg.init_size (options.zap_domain.length ());
315  errno_assert (rc == 0);
316  memcpy (msg.data (), options.zap_domain.c_str (), options.zap_domain.length ());
317  msg.set_flags (msg_t::more);
318  rc = session->write_zap_msg (&msg);
319  errno_assert (rc == 0);
320 
321  // Address frame
322  rc = msg.init_size (peer_address.length ());
323  errno_assert (rc == 0);
324  memcpy (msg.data (), peer_address.c_str (), peer_address.length ());
325  msg.set_flags (msg_t::more);
326  rc = session->write_zap_msg (&msg);
327  errno_assert (rc == 0);
328 
329  // Identity frame
330  rc = msg.init_size (options.identity_size);
331  errno_assert (rc == 0);
332  memcpy (msg.data (), options.identity, options.identity_size);
333  msg.set_flags (msg_t::more);
334  rc = session->write_zap_msg (&msg);
335  errno_assert (rc == 0);
336 
337  // Mechanism frame
338  rc = msg.init_size (5);
339  errno_assert (rc == 0);
340  memcpy (msg.data (), "PLAIN", 5);
341  msg.set_flags (msg_t::more);
342  rc = session->write_zap_msg (&msg);
343  errno_assert (rc == 0);
344 
345  // Username frame
346  rc = msg.init_size (username.length ());
347  errno_assert (rc == 0);
348  memcpy (msg.data (), username.c_str (), username.length ());
349  msg.set_flags (msg_t::more);
350  rc = session->write_zap_msg (&msg);
351  errno_assert (rc == 0);
352 
353  // Password frame
354  rc = msg.init_size (password.length ());
355  errno_assert (rc == 0);
356  memcpy (msg.data (), password.c_str (), password.length ());
357  rc = session->write_zap_msg (&msg);
358  errno_assert (rc == 0);
359 }
360 
362 {
363  int rc = 0;
364  msg_t msg [7]; // ZAP reply consists of 7 frames
365 
366  // Initialize all reply frames
367  for (int i = 0; i < 7; i++) {
368  rc = msg [i].init ();
369  errno_assert (rc == 0);
370  }
371 
372  for (int i = 0; i < 7; i++) {
373  rc = session->read_zap_msg (&msg [i]);
374  if (rc == -1)
375  break;
376  if ((msg [i].flags () & msg_t::more) == (i < 6? 0: msg_t::more)) {
377  // Temporary support for security debugging
378  puts ("PLAIN I: ZAP handler sent incomplete reply message");
379  errno = EPROTO;
380  rc = -1;
381  break;
382  }
383  }
384 
385  if (rc != 0)
386  goto error;
387 
388  // Address delimiter frame
389  if (msg [0].size () > 0) {
390  // Temporary support for security debugging
391  puts ("PLAIN I: ZAP handler sent malformed reply message");
392  errno = EPROTO;
393  rc = -1;
394  goto error;
395  }
396 
397  // Version frame
398  if (msg [1].size () != 3 || memcmp (msg [1].data (), "1.0", 3)) {
399  // Temporary support for security debugging
400  puts ("PLAIN I: ZAP handler sent bad version number");
401  errno = EPROTO;
402  rc = -1;
403  goto error;
404  }
405 
406  // Request id frame
407  if (msg [2].size () != 1 || memcmp (msg [2].data (), "1", 1)) {
408  // Temporary support for security debugging
409  puts ("PLAIN I: ZAP handler sent bad request ID");
410  rc = -1;
411  errno = EPROTO;
412  goto error;
413  }
414 
415  // Status code frame
416  if (msg [3].size () != 3) {
417  // Temporary support for security debugging
418  puts ("PLAIN I: ZAP handler rejected client authentication");
419  errno = EACCES;
420  rc = -1;
421  goto error;
422  }
423 
424  // Save status code
425  status_code.assign (static_cast <char *> (msg [3].data ()), 3);
426 
427  // Save user id
428  set_user_id (msg [5].data (), msg [5].size ());
429 
430  // Process metadata frame
431  rc = parse_metadata (static_cast <const unsigned char*> (msg [6].data ()),
432  msg [6].size (), true);
433 
434 error:
435  for (int i = 0; i < 7; i++) {
436  const int rc2 = msg [i].close ();
437  errno_assert (rc2 == 0);
438  }
439 
440  return rc;
441 }
#define size
#define EFSM
Definition: zmq.h:167
int close()
Definition: msg.cpp:217
int produce_error(msg_t *msg_) const
int process_initiate(msg_t *msg_)
#define ZMQ_DEALER
Definition: zmq.h:251
#define zmq_assert(x)
Definition: err.hpp:119
virtual int zap_msg_available()
virtual status_t status() const
int receive_and_process_zap_reply()
#define ZMQ_ROUTER
Definition: zmq.h:252
unsigned char size
Definition: msg.hpp:188
int write_zap_msg(msg_t *msg_)
int init_size(size_t size_)
Definition: msg.cpp:93
virtual int next_handshake_command(msg_t *msg_)
int produce_welcome(msg_t *msg_) const
options_t options
Definition: mechanism.hpp:124
const std::string peer_address
#define ZMQ_REQ
Definition: zmq.h:249
void send_zap_request(const std::string &username, const std::string &password)
int init()
Definition: msg.cpp:82
int parse_metadata(const unsigned char *ptr_, size_t length, bool zap_flag=false)
Definition: mechanism.cpp:102
unsigned char identity[256]
Definition: options.hpp:74
int read_zap_msg(msg_t *msg_)
#define EPROTO
Definition: err.hpp:58
const char * socket_type_string(int socket_type) const
Definition: mechanism.cpp:74
void set_flags(unsigned char flags_)
Definition: msg.cpp:384
virtual int process_handshake_command(msg_t *msg_)
session_base_t *const session
#define alloc_assert(x)
Definition: err.hpp:159
#define errno_assert(x)
Definition: err.hpp:129
int produce_ready(msg_t *msg_) const
std::string status_code
unsigned char data[max_vsm_size]
Definition: msg.hpp:187
plain_server_t(session_base_t *session_, const std::string &peer_address_, const options_t &options_)
std::string zap_domain
Definition: options.hpp:186
virtual ~plain_server_t()
int process_hello(msg_t *msg_)
size_t add_property(unsigned char *ptr, const char *name, const void *value, size_t value_len) const
Definition: mechanism.cpp:86
unsigned char identity_size
Definition: options.hpp:73
void set_user_id(const void *user_id, size_t size)
Definition: mechanism.cpp:61