zap_client.cpp 10.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
/*
    Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file

    This file is part of libzmq, the ZeroMQ core engine in C++.

    libzmq is free software; you can redistribute it and/or modify it under
    the terms of the GNU Lesser General Public License (LGPL) as published
    by the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    As a special exception, the Contributors give you permission to link
    this library with independent modules to produce an executable,
    regardless of the license terms of these independent modules, and to
    copy and distribute the resulting executable under terms of your choice,
    provided that you also meet, for each linked independent module, the
    terms and conditions of the license of that module. An independent
    module is a module which is not derived from or based on this library.
    If you modify this library, you must extend this exception to your
    version of the library.

    libzmq is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
    License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "precompiled.hpp"

#include "zap_client.hpp"
#include "msg.hpp"
34
#include "session_base.hpp"
35 36 37

namespace zmq
{
38 39 40 41 42 43
const char zap_version[] = "1.0";
const size_t zap_version_len = sizeof (zap_version) - 1;

const char id[] = "1";
const size_t id_len = sizeof (id) - 1;

44 45 46
zap_client_t::zap_client_t (session_base_t *const session_,
                            const std::string &peer_address_,
                            const options_t &options_) :
47
    mechanism_base_t (session_, options_),
48
    peer_address (peer_address_)
49 50 51
{
}

52 53 54 55
void zap_client_t::send_zap_request (const char *mechanism_,
                                     size_t mechanism_length_,
                                     const uint8_t *credentials_,
                                     size_t credentials_size_)
56
{
57 58
    send_zap_request (mechanism_, mechanism_length_, &credentials_,
                      &credentials_size_, 1);
59 60
}

61 62 63 64 65
void zap_client_t::send_zap_request (const char *mechanism_,
                                     size_t mechanism_length_,
                                     const uint8_t **credentials_,
                                     size_t *credentials_sizes_,
                                     size_t credentials_count_)
66
{
67 68
    // write_zap_msg cannot fail. It could only fail if the HWM was exceeded,
    // but on the ZAP socket, the HWM is disabled.
69 70 71 72 73 74 75 76 77

    int rc;
    msg_t msg;

    //  Address delimiter frame
    rc = msg.init ();
    errno_assert (rc == 0);
    msg.set_flags (msg_t::more);
    rc = session->write_zap_msg (&msg);
78
    errno_assert (rc == 0);
79 80

    //  Version frame
81
    rc = msg.init_size (zap_version_len);
82
    errno_assert (rc == 0);
83
    memcpy (msg.data (), zap_version, zap_version_len);
84 85
    msg.set_flags (msg_t::more);
    rc = session->write_zap_msg (&msg);
86
    errno_assert (rc == 0);
87 88

    //  Request ID frame
89
    rc = msg.init_size (id_len);
90
    errno_assert (rc == 0);
91
    memcpy (msg.data (), id, id_len);
92 93
    msg.set_flags (msg_t::more);
    rc = session->write_zap_msg (&msg);
94
    errno_assert (rc == 0);
95 96 97 98 99 100 101 102

    //  Domain frame
    rc = msg.init_size (options.zap_domain.length ());
    errno_assert (rc == 0);
    memcpy (msg.data (), options.zap_domain.c_str (),
            options.zap_domain.length ());
    msg.set_flags (msg_t::more);
    rc = session->write_zap_msg (&msg);
103
    errno_assert (rc == 0);
104 105 106 107 108 109 110

    //  Address frame
    rc = msg.init_size (peer_address.length ());
    errno_assert (rc == 0);
    memcpy (msg.data (), peer_address.c_str (), peer_address.length ());
    msg.set_flags (msg_t::more);
    rc = session->write_zap_msg (&msg);
111
    errno_assert (rc == 0);
112

113 114
    //  Routing id frame
    rc = msg.init_size (options.routing_id_size);
115
    errno_assert (rc == 0);
116
    memcpy (msg.data (), options.routing_id, options.routing_id_size);
117 118
    msg.set_flags (msg_t::more);
    rc = session->write_zap_msg (&msg);
119
    errno_assert (rc == 0);
120 121

    //  Mechanism frame
122
    rc = msg.init_size (mechanism_length_);
123
    errno_assert (rc == 0);
124 125
    memcpy (msg.data (), mechanism_, mechanism_length_);
    if (credentials_count_)
126
        msg.set_flags (msg_t::more);
127
    rc = session->write_zap_msg (&msg);
128
    errno_assert (rc == 0);
129

130
    //  Credentials frames
131 132
    for (size_t i = 0; i < credentials_count_; ++i) {
        rc = msg.init_size (credentials_sizes_[i]);
133
        errno_assert (rc == 0);
134
        if (i < credentials_count_ - 1)
135
            msg.set_flags (msg_t::more);
136
        memcpy (msg.data (), credentials_[i], credentials_sizes_[i]);
137
        rc = session->write_zap_msg (&msg);
138
        errno_assert (rc == 0);
139
    }
140
}
141 142 143 144

int zap_client_t::receive_and_process_zap_reply ()
{
    int rc = 0;
145 146
    const size_t zap_reply_frame_count = 7;
    msg_t msg[zap_reply_frame_count];
147 148

    //  Initialize all reply frames
149
    for (size_t i = 0; i < zap_reply_frame_count; i++) {
150 151 152 153
        rc = msg[i].init ();
        errno_assert (rc == 0);
    }

154
    for (size_t i = 0; i < zap_reply_frame_count; i++) {
155
        rc = session->read_zap_msg (&msg[i]);
156 157 158 159
        if (rc == -1) {
            if (errno == EAGAIN) {
                return 1;
            }
160
            return close_and_return (msg, -1);
161
        }
162 163
        if ((msg[i].flags () & msg_t::more)
            == (i < zap_reply_frame_count - 1 ? 0 : msg_t::more)) {
164 165
            session->get_socket ()->event_handshake_failed_protocol (
              session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZAP_MALFORMED_REPLY);
166 167 168 169 170 171 172
            errno = EPROTO;
            return close_and_return (msg, -1);
        }
    }

    //  Address delimiter frame
    if (msg[0].size () > 0) {
173 174 175
        //  TODO can a ZAP handler produce such a message at all?
        session->get_socket ()->event_handshake_failed_protocol (
          session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZAP_UNSPECIFIED);
176 177 178 179 180
        errno = EPROTO;
        return close_and_return (msg, -1);
    }

    //  Version frame
181 182
    if (msg[1].size () != zap_version_len
        || memcmp (msg[1].data (), zap_version, zap_version_len)) {
183 184
        session->get_socket ()->event_handshake_failed_protocol (
          session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZAP_BAD_VERSION);
185 186 187 188 189
        errno = EPROTO;
        return close_and_return (msg, -1);
    }

    //  Request id frame
190
    if (msg[2].size () != id_len || memcmp (msg[2].data (), id, id_len)) {
191 192
        session->get_socket ()->event_handshake_failed_protocol (
          session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZAP_BAD_REQUEST_ID);
193 194 195 196 197
        errno = EPROTO;
        return close_and_return (msg, -1);
    }

    //  Status code frame, only 200, 300, 400 and 500 are valid status codes
198
    const char *status_code_data = static_cast<const char *> (msg[3].data ());
199 200 201
    if (msg[3].size () != 3 || status_code_data[0] < '2'
        || status_code_data[0] > '5' || status_code_data[1] != '0'
        || status_code_data[2] != '0') {
202 203
        session->get_socket ()->event_handshake_failed_protocol (
          session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZAP_INVALID_STATUS_CODE);
204 205 206 207 208 209 210 211 212 213 214 215 216 217
        errno = EPROTO;
        return close_and_return (msg, -1);
    }

    //  Save status code
    status_code.assign (static_cast<char *> (msg[3].data ()), 3);

    //  Save user id
    set_user_id (msg[5].data (), msg[5].size ());

    //  Process metadata frame
    rc = parse_metadata (static_cast<const unsigned char *> (msg[6].data ()),
                         msg[6].size (), true);

218
    if (rc != 0) {
219 220 221
        session->get_socket ()->event_handshake_failed_protocol (
          session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZAP_INVALID_METADATA);
        errno = EPROTO;
222
        return close_and_return (msg, -1);
223
    }
224 225

    //  Close all reply frames
226
    for (size_t i = 0; i < zap_reply_frame_count; i++) {
227 228 229 230
        const int rc2 = msg[i].close ();
        errno_assert (rc2 == 0);
    }

231 232
    handle_zap_status_code ();

233 234
    return 0;
}
235

236 237 238 239
void zap_client_t::handle_zap_status_code ()
{
    //  we can assume here that status_code is a valid ZAP status code,
    //  i.e. 200, 300, 400 or 500
240
    int status_code_numeric = 0;
241 242 243 244
    switch (status_code[0]) {
        case '2':
            return;
        case '3':
245
            status_code_numeric = 300;
246 247
            break;
        case '4':
248
            status_code_numeric = 400;
249 250
            break;
        case '5':
251
            status_code_numeric = 500;
252 253 254
            break;
    }

255 256
    session->get_socket ()->event_handshake_failed_auth (
      session->get_endpoint (), status_code_numeric);
257 258
}

259 260 261
zap_client_common_handshake_t::zap_client_common_handshake_t (
  session_base_t *const session_,
  const std::string &peer_address_,
262 263
  const options_t &options_,
  state_t zap_reply_ok_state_) :
264
    mechanism_base_t (session_, options_),
265
    zap_client_t (session_, peer_address_, options_),
266
    state (waiting_for_hello),
267
    _zap_reply_ok_state (zap_reply_ok_state_)
268 269 270 271 272 273 274
{
}

zmq::mechanism_t::status_t zap_client_common_handshake_t::status () const
{
    if (state == ready)
        return mechanism_t::ready;
275
    if (state == error_sent)
276 277 278 279
        return mechanism_t::error;
    else
        return mechanism_t::handshaking;
}
280 281 282

int zap_client_common_handshake_t::zap_msg_available ()
{
283
    zmq_assert (state == waiting_for_zap_reply);
284
    return receive_and_process_zap_reply () == -1 ? -1 : 0;
285 286 287 288
}

void zap_client_common_handshake_t::handle_zap_status_code ()
{
289 290
    zap_client_t::handle_zap_status_code ();

291 292
    //  we can assume here that status_code is a valid ZAP status code,
    //  i.e. 200, 300, 400 or 500
293 294
    switch (status_code[0]) {
        case '2':
295
            state = _zap_reply_ok_state;
296 297 298 299 300 301 302 303 304 305
            break;
        case '3':
            //  a 300 error code (temporary failure)
            //  should NOT result in an ERROR message, but instead the
            //  client should be silently disconnected (see CURVEZMQ RFC)
            //  therefore, go immediately to state error_sent
            state = error_sent;
            break;
        default:
            state = sending_error;
306 307 308
    }
}

309 310
int zap_client_common_handshake_t::receive_and_process_zap_reply ()
{
311 312
    zmq_assert (state == waiting_for_zap_reply);
    return zap_client_t::receive_and_process_zap_reply ();
313
}
314
}