plain_server.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MPL-2.0 */
2 
3 #include "precompiled.hpp"
4 
5 #include <string>
6 
7 #include "msg.hpp"
8 #include "session_base.hpp"
9 #include "err.hpp"
10 #include "plain_server.hpp"
11 #include "wire.hpp"
12 #include "plain_common.hpp"
13 
14 zmq::plain_server_t::plain_server_t (session_base_t *session_,
15  const std::string &peer_address_,
16  const options_t &options_) :
17  mechanism_base_t (session_, options_),
18  zap_client_common_handshake_t (
19  session_, peer_address_, options_, sending_welcome)
20 {
21  // Note that there is no point to PLAIN if ZAP is not set up to handle the
22  // username and password, so if ZAP is not configured it is considered a
23  // failure.
24  // Given this is a backward-incompatible change, it's behind a socket
25  // option disabled by default.
26  if (options.zap_enforce_domain)
27  zmq_assert (zap_required ());
28 }
29 
30 zmq::plain_server_t::~plain_server_t ()
31 {
32 }
33 
34 int zmq::plain_server_t::next_handshake_command (msg_t *msg_)
35 {
36  int rc = 0;
37 
38  switch (state) {
39  case sending_welcome:
40  produce_welcome (msg_);
41  state = waiting_for_initiate;
42  break;
43  case sending_ready:
44  produce_ready (msg_);
45  state = ready;
46  break;
47  case sending_error:
48  produce_error (msg_);
49  state = error_sent;
50  break;
51  default:
52  errno = EAGAIN;
53  rc = -1;
54  }
55  return rc;
56 }
57 
58 int zmq::plain_server_t::process_handshake_command (msg_t *msg_)
59 {
60  int rc = 0;
61 
62  switch (state) {
63  case waiting_for_hello:
64  rc = process_hello (msg_);
65  break;
66  case waiting_for_initiate:
67  rc = process_initiate (msg_);
68  break;
69  default:
70  // TODO see comment in curve_server_t::process_handshake_command
71  session->get_socket ()->event_handshake_failed_protocol (
72  session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_UNSPECIFIED);
73  errno = EPROTO;
74  rc = -1;
75  break;
76  }
77  if (rc == 0) {
78  rc = msg_->close ();
79  errno_assert (rc == 0);
80  rc = msg_->init ();
81  errno_assert (rc == 0);
82  }
83  return rc;
84 }
85 
86 int zmq::plain_server_t::process_hello (msg_t *msg_)
87 {
88  int rc = check_basic_command_structure (msg_);
89  if (rc == -1)
90  return -1;
91 
92  const char *ptr = static_cast<char *> (msg_->data ());
93  size_t bytes_left = msg_->size ();
94 
95  if (bytes_left < hello_prefix_len
96  || memcmp (ptr, hello_prefix, hello_prefix_len) != 0) {
97  session->get_socket ()->event_handshake_failed_protocol (
98  session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND);
99  errno = EPROTO;
100  return -1;
101  }
102  ptr += hello_prefix_len;
103  bytes_left -= hello_prefix_len;
104 
105  if (bytes_left < 1) {
106  // PLAIN I: invalid PLAIN client, did not send username
107  session->get_socket ()->event_handshake_failed_protocol (
108  session->get_endpoint (),
110  errno = EPROTO;
111  return -1;
112  }
113  const uint8_t username_length = *ptr++;
114  bytes_left -= sizeof (username_length);
115 
116  if (bytes_left < username_length) {
117  // PLAIN I: invalid PLAIN client, sent malformed username
118  session->get_socket ()->event_handshake_failed_protocol (
119  session->get_endpoint (),
121  errno = EPROTO;
122  return -1;
123  }
124  const std::string username = std::string (ptr, username_length);
125  ptr += username_length;
126  bytes_left -= username_length;
127  if (bytes_left < 1) {
128  // PLAIN I: invalid PLAIN client, did not send password
129  session->get_socket ()->event_handshake_failed_protocol (
130  session->get_endpoint (),
132  errno = EPROTO;
133  return -1;
134  }
135 
136  const uint8_t password_length = *ptr++;
137  bytes_left -= sizeof (password_length);
138  if (bytes_left != password_length) {
139  // PLAIN I: invalid PLAIN client, sent malformed password or
140  // extraneous data
141  session->get_socket ()->event_handshake_failed_protocol (
142  session->get_endpoint (),
144  errno = EPROTO;
145  return -1;
146  }
147 
148  const std::string password = std::string (ptr, password_length);
149 
150  // Use ZAP protocol (RFC 27) to authenticate the user.
151  rc = session->zap_connect ();
152  if (rc != 0) {
153  session->get_socket ()->event_handshake_failed_no_detail (
154  session->get_endpoint (), EFAULT);
155  return -1;
156  }
157 
158  send_zap_request (username, password);
159  state = waiting_for_zap_reply;
160 
161  // TODO actually, it is quite unlikely that we can read the ZAP
162  // reply already, but removing this has some strange side-effect
163  // (probably because the pipe's in_active flag is true until a read
164  // is attempted)
165  return receive_and_process_zap_reply () == -1 ? -1 : 0;
166 }
167 
168 void zmq::plain_server_t::produce_welcome (msg_t *msg_)
169 {
170  const int rc = msg_->init_size (welcome_prefix_len);
171  errno_assert (rc == 0);
172  memcpy (msg_->data (), welcome_prefix, welcome_prefix_len);
173 }
174 
175 int zmq::plain_server_t::process_initiate (msg_t *msg_)
176 {
177  const unsigned char *ptr = static_cast<unsigned char *> (msg_->data ());
178  const size_t bytes_left = msg_->size ();
179 
180  if (bytes_left < initiate_prefix_len
181  || memcmp (ptr, initiate_prefix, initiate_prefix_len) != 0) {
182  session->get_socket ()->event_handshake_failed_protocol (
183  session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND);
184  errno = EPROTO;
185  return -1;
186  }
187  const int rc = parse_metadata (ptr + initiate_prefix_len,
188  bytes_left - initiate_prefix_len);
189  if (rc == 0)
190  state = sending_ready;
191  return rc;
192 }
193 
194 void zmq::plain_server_t::produce_ready (msg_t *msg_) const
195 {
196  make_command_with_basic_properties (msg_, ready_prefix, ready_prefix_len);
197 }
198 
199 void zmq::plain_server_t::produce_error (msg_t *msg_) const
200 {
201  const char expected_status_code_len = 3;
202  zmq_assert (status_code.length ()
203  == static_cast<size_t> (expected_status_code_len));
204  const size_t status_code_len_size = sizeof (expected_status_code_len);
205  const int rc = msg_->init_size (error_prefix_len + status_code_len_size
206  + expected_status_code_len);
207  zmq_assert (rc == 0);
208  char *msg_data = static_cast<char *> (msg_->data ());
209  memcpy (msg_data, error_prefix, error_prefix_len);
210  msg_data[error_prefix_len] = expected_status_code_len;
211  memcpy (msg_data + error_prefix_len + status_code_len_size,
212  status_code.c_str (), status_code.length ());
213 }
214 
215 void zmq::plain_server_t::send_zap_request (const std::string &username_,
216  const std::string &password_)
217 {
218  const uint8_t *credentials[] = {
219  reinterpret_cast<const uint8_t *> (username_.c_str ()),
220  reinterpret_cast<const uint8_t *> (password_.c_str ())};
221  size_t credentials_sizes[] = {username_.size (), password_.size ()};
222  const char plain_mechanism_name[] = "PLAIN";
223  zap_client_t::send_zap_request (
224  plain_mechanism_name, sizeof (plain_mechanism_name) - 1, credentials,
225  credentials_sizes, sizeof (credentials) / sizeof (credentials[0]));
226 }
ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND
#define ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND
Definition: zmq.h:425
zmq::initiate_prefix
const char initiate_prefix[]
Definition: plain_common.hpp:14
options
Message * options
Definition: src/google/protobuf/descriptor.cc:3119
zmq::ready_prefix
const char ready_prefix[]
Definition: plain_common.hpp:17
EAGAIN
#define EAGAIN
Definition: errno.hpp:14
precompiled.hpp
zmq_assert
#define zmq_assert(x)
Definition: err.hpp:102
string
GLsizei const GLchar *const * string
Definition: glcorearb.h:3083
errno
int errno
zmq::ready_prefix_len
const size_t ready_prefix_len
Definition: plain_common.hpp:18
plain_common.hpp
zmq::hello_prefix_len
const size_t hello_prefix_len
Definition: plain_common.hpp:9
wire.hpp
EPROTO
#define EPROTO
Definition: err.hpp:26
zmq::hello_prefix
const char hello_prefix[]
Definition: plain_common.hpp:8
errno_assert
#define errno_assert(x)
Definition: err.hpp:113
ZMQ_PROTOCOL_ERROR_ZMTP_UNSPECIFIED
#define ZMQ_PROTOCOL_ERROR_ZMTP_UNSPECIFIED
Definition: zmq.h:424
zmq::error_prefix_len
const size_t error_prefix_len
Definition: plain_common.hpp:21
zmq::welcome_prefix_len
const size_t welcome_prefix_len
Definition: plain_common.hpp:12
plain_server.hpp
msg.hpp
zmq::welcome_prefix
const char welcome_prefix[]
Definition: plain_common.hpp:11
err.hpp
ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_HELLO
#define ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_HELLO
Definition: zmq.h:430
zmq::initiate_prefix_len
const size_t initiate_prefix_len
Definition: plain_common.hpp:15
session_base.hpp
EFAULT
#define EFAULT
Definition: errno.hpp:17
options_
DebugStringOptions options_
Definition: src/google/protobuf/descriptor.cc:2410
zmq::error_prefix
const char error_prefix[]
Definition: plain_common.hpp:20


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:57