libzmq  master
ZeroMQ C++ Core Engine (LIBZMQ)
plain_client.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 "macros.hpp"
32 #include "platform.hpp"
33 #ifdef ZMQ_HAVE_WINDOWS
34 #include "windows.hpp"
35 #endif
36 
37 #include <string>
38 
39 #include "msg.hpp"
40 #include "err.hpp"
41 #include "plain_client.hpp"
42 
44  mechanism_t (options_),
45  state (sending_hello)
46 {
47 }
48 
50 {
51 }
52 
54 {
55  int rc = 0;
56 
57  switch (state) {
58  case sending_hello:
59  rc = produce_hello (msg_);
60  if (rc == 0)
62  break;
63  case sending_initiate:
64  rc = produce_initiate (msg_);
65  if (rc == 0)
67  break;
68  default:
69  errno = EAGAIN;
70  rc = -1;
71  }
72  return rc;
73 }
74 
76 {
77  const unsigned char *cmd_data =
78  static_cast <unsigned char *> (msg_->data ());
79  const size_t data_size = msg_->size ();
80 
81  int rc = 0;
82  if (data_size >= 8 && !memcmp (cmd_data, "\7WELCOME", 8))
83  rc = process_welcome (cmd_data, data_size);
84  else
85  if (data_size >= 6 && !memcmp (cmd_data, "\5READY", 6))
86  rc = process_ready (cmd_data, data_size);
87  else
88  if (data_size >= 6 && !memcmp (cmd_data, "\5ERROR", 6))
89  rc = process_error (cmd_data, data_size);
90  else {
91  // Temporary support for security debugging
92  puts ("PLAIN I: invalid handshake command");
93  errno = EPROTO;
94  rc = -1;
95  }
96 
97  if (rc == 0) {
98  rc = msg_->close ();
99  errno_assert (rc == 0);
100  rc = msg_->init ();
101  errno_assert (rc == 0);
102  }
103 
104  return rc;
105 }
106 
108 {
109  if (state == ready)
110  return mechanism_t::ready;
111  else
113  return mechanism_t::error;
114  else
116 }
117 
119 {
120  const std::string username = options.plain_username;
121  zmq_assert (username.length () < 256);
122 
123  const std::string password = options.plain_password;
124  zmq_assert (password.length () < 256);
125 
126  const size_t command_size = 6 + 1 + username.length ()
127  + 1 + password.length ();
128 
129  const int rc = msg_->init_size (command_size);
130  errno_assert (rc == 0);
131 
132  unsigned char *ptr = static_cast <unsigned char *> (msg_->data ());
133  memcpy (ptr, "\x05HELLO", 6);
134  ptr += 6;
135 
136  *ptr++ = static_cast <unsigned char> (username.length ());
137  memcpy (ptr, username.c_str (), username.length ());
138  ptr += username.length ();
139 
140  *ptr++ = static_cast <unsigned char> (password.length ());
141  memcpy (ptr, password.c_str (), password.length ());
142  ptr += password.length ();
143 
144  return 0;
145 }
146 
148  const unsigned char *cmd_data, size_t data_size)
149 {
150  LIBZMQ_UNUSED (cmd_data);
151 
152  if (state != waiting_for_welcome) {
153  errno = EPROTO;
154  return -1;
155  }
156  if (data_size != 8) {
157  errno = EPROTO;
158  return -1;
159  }
161  return 0;
162 }
163 
165 {
166  unsigned char * const command_buffer = (unsigned char *) malloc (512);
167  alloc_assert (command_buffer);
168 
169  unsigned char *ptr = command_buffer;
170 
171  // Add mechanism string
172  memcpy (ptr, "\x08INITIATE", 9);
173  ptr += 9;
174 
175  // Add socket type property
176  const char *socket_type = socket_type_string (options.type);
177  ptr += add_property (ptr, "Socket-Type", socket_type, strlen (socket_type));
178 
179  // Add identity property
180  if (options.type == ZMQ_REQ
181  || options.type == ZMQ_DEALER
182  || options.type == ZMQ_ROUTER)
183  ptr += add_property (
184  ptr, "Identity", options.identity, options.identity_size);
185 
186  const size_t command_size = ptr - command_buffer;
187  const int rc = msg_->init_size (command_size);
188  errno_assert (rc == 0);
189  memcpy (msg_->data (), command_buffer, command_size);
190  free (command_buffer);
191 
192  return 0;
193 }
194 
196  const unsigned char *cmd_data, size_t data_size)
197 {
198  if (state != waiting_for_ready) {
199  errno = EPROTO;
200  return -1;
201  }
202  const int rc = parse_metadata (cmd_data + 6, data_size - 6);
203  if (rc == 0)
204  state = ready;
205  return rc;
206 }
207 
209  const unsigned char *cmd_data, size_t data_size)
210 {
212  errno = EPROTO;
213  return -1;
214  }
215  if (data_size < 7) {
216  errno = EPROTO;
217  return -1;
218  }
219  const size_t error_reason_len = static_cast <size_t> (cmd_data [6]);
220  if (error_reason_len > data_size - 7) {
221  errno = EPROTO;
222  return -1;
223  }
225  return 0;
226 }
std::string plain_username
Definition: options.hpp:189
int close()
Definition: msg.cpp:217
virtual ~plain_client_t()
#define ZMQ_DEALER
Definition: zmq.h:251
#define zmq_assert(x)
Definition: err.hpp:119
int process_error(const unsigned char *cmd_data, size_t data_size)
int process_ready(const unsigned char *cmd_data, size_t data_size)
int produce_hello(msg_t *msg_) const
int process_welcome(const unsigned char *cmd_data, size_t data_size)
#define ZMQ_ROUTER
Definition: zmq.h:252
unsigned char size
Definition: msg.hpp:188
int init_size(size_t size_)
Definition: msg.cpp:93
options_t options
Definition: mechanism.hpp:124
#define ZMQ_REQ
Definition: zmq.h:249
#define LIBZMQ_UNUSED(object)
Definition: macros.hpp:6
virtual int next_handshake_command(msg_t *msg_)
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
std::string plain_password
Definition: options.hpp:190
virtual int process_handshake_command(msg_t *msg_)
int produce_initiate(msg_t *msg_) const
#define EPROTO
Definition: err.hpp:58
const char * socket_type_string(int socket_type) const
Definition: mechanism.cpp:74
#define alloc_assert(x)
Definition: err.hpp:159
#define errno_assert(x)
Definition: err.hpp:129
unsigned char data[max_vsm_size]
Definition: msg.hpp:187
virtual status_t status() const
plain_client_t(const options_t &options_)
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