zap_client.cpp 9.89 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
zap_client_t::zap_client_t (session_base_t *const session_,
                            const std::string &peer_address_,
                            const options_t &options_) :
41
    mechanism_base_t (session_, options_),
42
    peer_address (peer_address_)
43 44 45
{
}

46
void zap_client_t::send_zap_request (const char *mechanism,
47 48 49
                                    size_t mechanism_length,
                                    const uint8_t *credentials,
                                    size_t credentials_size)
50
{
51 52
    send_zap_request (mechanism, mechanism_length, &credentials,
                      &credentials_size, 1);
53 54
}

55
void zap_client_t::send_zap_request (const char *mechanism,
56 57 58 59
                                    size_t mechanism_length,
                                    const uint8_t **credentials,
                                    size_t *credentials_sizes,
                                    size_t credentials_count)
60
{
61 62
    // write_zap_msg cannot fail. It could only fail if the HWM was exceeded, 
    // but on the ZAP socket, the HWM is disabled. 
63 64 65 66 67 68 69 70 71

    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);
72
    errno_assert (rc == 0);
73 74 75 76 77 78 79

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

    //  Request ID frame
    rc = msg.init_size (1);
    errno_assert (rc == 0);
    memcpy (msg.data (), "1", 1);
    msg.set_flags (msg_t::more);
    rc = session->write_zap_msg (&msg);
88
    errno_assert (rc == 0);
89 90 91 92 93 94 95 96

    //  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);
97
    errno_assert (rc == 0);
98 99 100 101 102 103 104

    //  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);
105
    errno_assert (rc == 0);
106

107 108
    //  Routing id frame
    rc = msg.init_size (options.routing_id_size);
109
    errno_assert (rc == 0);
110
    memcpy (msg.data (), options.routing_id, options.routing_id_size);
111 112
    msg.set_flags (msg_t::more);
    rc = session->write_zap_msg (&msg);
113
    errno_assert (rc == 0);
114 115 116 117 118

    //  Mechanism frame
    rc = msg.init_size (mechanism_length);
    errno_assert (rc == 0);
    memcpy (msg.data (), mechanism, mechanism_length);
119
    if (credentials_count)
120
        msg.set_flags (msg_t::more);
121
    rc = session->write_zap_msg (&msg);
122
    errno_assert (rc == 0);
123

124 125 126
    //  Credentials frames
    for (size_t i = 0; i < credentials_count; ++i) {
        rc = msg.init_size (credentials_sizes[i]);
127
        errno_assert (rc == 0);
128 129 130
        if (i < credentials_count - 1)
            msg.set_flags (msg_t::more);
        memcpy (msg.data (), credentials[i], credentials_sizes[i]);
131
        rc = session->write_zap_msg (&msg);
132
        errno_assert (rc == 0);
133
    }
134
}
135 136 137 138 139 140 141 142 143 144 145 146 147 148

int zap_client_t::receive_and_process_zap_reply ()
{
    int rc = 0;
    msg_t msg[7]; //  ZAP reply consists of 7 frames

    //  Initialize all reply frames
    for (int i = 0; i < 7; i++) {
        rc = msg[i].init ();
        errno_assert (rc == 0);
    }

    for (int i = 0; i < 7; i++) {
        rc = session->read_zap_msg (&msg[i]);
149 150 151 152
        if (rc == -1) {
            if (errno == EAGAIN) {
                return 1;
            }
153
            return close_and_return (msg, -1);
154
        }
155
        if ((msg[i].flags () & msg_t::more) == (i < 6 ? 0 : msg_t::more)) {
156 157
            session->get_socket ()->event_handshake_failed_protocol (
              session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZAP_MALFORMED_REPLY);
158 159 160 161 162 163 164
            errno = EPROTO;
            return close_and_return (msg, -1);
        }
    }

    //  Address delimiter frame
    if (msg[0].size () > 0) {
165 166 167
        //  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);
168 169 170 171 172 173
        errno = EPROTO;
        return close_and_return (msg, -1);
    }

    //  Version frame
    if (msg[1].size () != 3 || memcmp (msg[1].data (), "1.0", 3)) {
174 175
        session->get_socket ()->event_handshake_failed_protocol (
          session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZAP_BAD_VERSION);
176 177 178 179 180 181
        errno = EPROTO;
        return close_and_return (msg, -1);
    }

    //  Request id frame
    if (msg[2].size () != 1 || memcmp (msg[2].data (), "1", 1)) {
182 183
        session->get_socket ()->event_handshake_failed_protocol (
          session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZAP_BAD_REQUEST_ID);
184 185 186 187 188 189 190 191 192
        errno = EPROTO;
        return close_and_return (msg, -1);
    }

    //  Status code frame, only 200, 300, 400 and 500 are valid status codes
    char *status_code_data = static_cast<char *> (msg[3].data ());
    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') {
193 194
        session->get_socket ()->event_handshake_failed_protocol (
          session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZAP_INVALID_STATUS_CODE);
195 196 197 198 199 200 201 202 203 204 205 206 207 208
        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);

209
    if (rc != 0) {
210 211 212
        session->get_socket ()->event_handshake_failed_protocol (
          session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZAP_INVALID_METADATA);
        errno = EPROTO;
213
        return close_and_return (msg, -1);
214
    }
215 216 217 218 219 220 221

    //  Close all reply frames
    for (int i = 0; i < 7; i++) {
        const int rc2 = msg[i].close ();
        errno_assert (rc2 == 0);
    }

222 223
    handle_zap_status_code ();

224 225
    return 0;
}
226

227 228 229 230
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
231
    int status_code_numeric = 0;
232 233 234 235
    switch (status_code[0]) {
        case '2':
            return;
        case '3':
236
            status_code_numeric = 300;
237 238
            break;
        case '4':
239
            status_code_numeric = 400;
240 241
            break;
        case '5':
242
            status_code_numeric = 500;
243 244 245
            break;
    }

246 247
    session->get_socket ()->event_handshake_failed_auth (
      session->get_endpoint (), status_code_numeric);
248 249
}

250 251 252
zap_client_common_handshake_t::zap_client_common_handshake_t (
  session_base_t *const session_,
  const std::string &peer_address_,
253 254
  const options_t &options_,
  state_t zap_reply_ok_state_) :
255
    mechanism_base_t (session_, options_),
256
    zap_client_t (session_, peer_address_, options_),
257 258
    state (waiting_for_hello),
    zap_reply_ok_state (zap_reply_ok_state_)
259 260 261 262 263 264 265 266 267 268 269 270
{
}

zmq::mechanism_t::status_t zap_client_common_handshake_t::status () const
{
    if (state == ready)
        return mechanism_t::ready;
    else if (state == error_sent)
        return mechanism_t::error;
    else
        return mechanism_t::handshaking;
}
271 272 273

int zap_client_common_handshake_t::zap_msg_available ()
{
274
    zmq_assert (state == waiting_for_zap_reply);
275
    return receive_and_process_zap_reply () == -1 ? -1 : 0;
276 277 278 279
}

void zap_client_common_handshake_t::handle_zap_status_code ()
{
280 281
    zap_client_t::handle_zap_status_code ();

282 283
    //  we can assume here that status_code is a valid ZAP status code,
    //  i.e. 200, 300, 400 or 500
284 285 286 287 288 289 290 291 292 293 294 295 296
    switch (status_code[0]) {
        case '2':
            state = zap_reply_ok_state;
            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;
297 298 299
    }
}

300 301
int zap_client_common_handshake_t::receive_and_process_zap_reply ()
{
302 303
    zmq_assert (state == waiting_for_zap_reply);
    return zap_client_t::receive_and_process_zap_reply ();
304
}
305
}