plain_server.cpp 12.7 KB
Newer Older
1
/*
2
    Copyright (c) 2007-2015 Contributors as noted in the AUTHORS file
3

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

6 7 8
    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
9 10
    (at your option) any later version.

11 12 13 14 15 16 17 18 19 20 21 22 23 24
    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.
25 26 27 28 29 30 31 32 33 34 35 36 37

    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 "platform.hpp"
#ifdef ZMQ_HAVE_WINDOWS
#include "windows.hpp"
#endif

#include <string>

#include "msg.hpp"
38
#include "session_base.hpp"
39
#include "err.hpp"
40
#include "plain_server.hpp"
41 42
#include "wire.hpp"

43 44 45
zmq::plain_server_t::plain_server_t (session_base_t *session_,
                                     const std::string &peer_address_,
                                     const options_t &options_) :
46
    mechanism_t (options_),
47
    session (session_),
48
    peer_address (peer_address_),
49
    state (waiting_for_hello)
50 51 52
{
}

53
zmq::plain_server_t::~plain_server_t ()
54 55 56
{
}

57
int zmq::plain_server_t::next_handshake_command (msg_t *msg_)
58 59 60 61
{
    int rc = 0;

    switch (state) {
62
        case sending_welcome:
63
            rc = produce_welcome (msg_);
64 65 66 67
            if (rc == 0)
                state = waiting_for_initiate;
            break;
        case sending_ready:
68
            rc = produce_ready (msg_);
69 70 71
            if (rc == 0)
                state = ready;
            break;
72 73 74 75 76
        case sending_error:
            rc = produce_error (msg_);
            if (rc == 0)
                state = error_command_sent;
            break;
77 78 79
        default:
            errno = EAGAIN;
            rc = -1;
80 81 82 83
    }
    return rc;
}

84
int zmq::plain_server_t::process_handshake_command (msg_t *msg_)
85 86 87 88
{
    int rc = 0;

    switch (state) {
89
        case waiting_for_hello:
90
            rc = process_hello (msg_);
91 92
            break;
        case waiting_for_initiate:
93
            rc = process_initiate (msg_);
94 95
            break;
        default:
96 97
            //  Temporary support for security debugging
            puts ("PLAIN I: invalid handshake command");
98
            errno = EPROTO;
99
            rc = -1;
100
            break;
101 102 103 104 105 106 107
    }
    if (rc == 0) {
        rc = msg_->close ();
        errno_assert (rc == 0);
        rc = msg_->init ();
        errno_assert (rc == 0);
    }
108
    return rc;
109 110
}

111
zmq::mechanism_t::status_t zmq::plain_server_t::status () const
112
{
113 114 115 116 117 118 119
    if (state == ready)
        return mechanism_t::ready;
    else
    if (state == error_command_sent)
        return mechanism_t::error;
    else
        return mechanism_t::handshaking;
120 121
}

122
int zmq::plain_server_t::zap_msg_available ()
123 124 125 126 127 128 129
{
    if (state != waiting_for_zap_reply) {
        errno = EFSM;
        return -1;
    }
    const int rc = receive_and_process_zap_reply ();
    if (rc == 0)
130 131 132
        state = status_code == "200"
            ? sending_welcome
            : sending_error;
133 134
    return rc;
}
135

136
int zmq::plain_server_t::process_hello (msg_t *msg_)
137 138 139 140
{
    const unsigned char *ptr = static_cast <unsigned char *> (msg_->data ());
    size_t bytes_left = msg_->size ();

141
    if (bytes_left < 6 || memcmp (ptr, "\x05HELLO", 6)) {
142 143
        //  Temporary support for security debugging
        puts ("PLAIN I: invalid PLAIN client, did not send HELLO");
144 145 146
        errno = EPROTO;
        return -1;
    }
147 148
    ptr += 6;
    bytes_left -= 6;
149 150

    if (bytes_left < 1) {
151 152
        //  Temporary support for security debugging
        puts ("PLAIN I: invalid PLAIN client, did not send username");
153 154 155
        errno = EPROTO;
        return -1;
    }
Martin Hurton's avatar
Martin Hurton committed
156
    const size_t username_length = static_cast <size_t> (*ptr++);
157 158 159
    bytes_left -= 1;

    if (bytes_left < username_length) {
160 161
        //  Temporary support for security debugging
        puts ("PLAIN I: invalid PLAIN client, sent malformed username");
162 163 164 165 166 167 168
        errno = EPROTO;
        return -1;
    }
    const std::string username = std::string ((char *) ptr, username_length);
    ptr += username_length;
    bytes_left -= username_length;
    if (bytes_left < 1) {
169 170
        //  Temporary support for security debugging
        puts ("PLAIN I: invalid PLAIN client, did not send password");
171 172 173
        errno = EPROTO;
        return -1;
    }
174

Martin Hurton's avatar
Martin Hurton committed
175
    const size_t password_length = static_cast <size_t> (*ptr++);
176 177
    bytes_left -= 1;
    if (bytes_left < password_length) {
178 179
        //  Temporary support for security debugging
        puts ("PLAIN I: invalid PLAIN client, sent malformed password");
180 181 182
        errno = EPROTO;
        return -1;
    }
183

184 185 186 187
    const std::string password = std::string ((char *) ptr, password_length);
    ptr += password_length;
    bytes_left -= password_length;
    if (bytes_left > 0) {
188 189
        //  Temporary support for security debugging
        puts ("PLAIN I: invalid PLAIN client, sent extraneous data");
190 191 192
        errno = EPROTO;
        return -1;
    }
193

194
    //  Use ZAP protocol (RFC 27) to authenticate the user.
195
    int rc = session->zap_connect ();
196 197 198
    if (rc == 0) {
        send_zap_request (username, password);
        rc = receive_and_process_zap_reply ();
199 200 201 202 203 204 205 206 207
        if (rc == 0)
            state = status_code == "200"
                ? sending_welcome
                : sending_error;
        else
        if (errno == EAGAIN)
            state = waiting_for_zap_reply;
        else
            return -1;
208
    }
209 210
    else
        state = sending_welcome;
211

212 213 214
    return 0;
}

215
int zmq::plain_server_t::produce_welcome (msg_t *msg_) const
216 217 218
{
    const int rc = msg_->init_size (8);
    errno_assert (rc == 0);
219
    memcpy (msg_->data (), "\x07WELCOME", 8);
220 221 222
    return 0;
}

223
int zmq::plain_server_t::process_initiate (msg_t *msg_)
224 225
{
    const unsigned char *ptr = static_cast <unsigned char *> (msg_->data ());
226
    const size_t bytes_left = msg_->size ();
227

228
    if (bytes_left < 9 || memcmp (ptr, "\x08INITIATE", 9)) {
229 230
        //  Temporary support for security debugging
        puts ("PLAIN I: invalid PLAIN client, did not send INITIATE");
231 232 233
        errno = EPROTO;
        return -1;
    }
234 235 236 237
    const int rc = parse_metadata (ptr + 9, bytes_left - 9);
    if (rc == 0)
        state = sending_ready;
    return rc;
238 239
}

240
int zmq::plain_server_t::produce_ready (msg_t *msg_) const
241 242 243 244 245 246
{
    unsigned char * const command_buffer = (unsigned char *) malloc (512);
    alloc_assert (command_buffer);

    unsigned char *ptr = command_buffer;

247
    //  Add command name
248
    memcpy (ptr, "\x05READY", 6);
249
    ptr += 6;
250 251 252 253 254 255 256 257

    //  Add socket type property
    const char *socket_type = socket_type_string (options.type);
    ptr += add_property (ptr, "Socket-Type", socket_type, strlen (socket_type));

    //  Add identity property
    if (options.type == ZMQ_REQ
    ||  options.type == ZMQ_DEALER
Pieter Hintjens's avatar
Pieter Hintjens committed
258
    ||  options.type == ZMQ_ROUTER)
259 260
        ptr += add_property (
            ptr, "Identity", options.identity, options.identity_size);
261 262 263 264 265 266 267 268 269 270

    const size_t command_size = ptr - command_buffer;
    const int rc = msg_->init_size (command_size);
    errno_assert (rc == 0);
    memcpy (msg_->data (), command_buffer, command_size);
    free (command_buffer);

    return 0;
}

271 272 273
int zmq::plain_server_t::produce_error (msg_t *msg_) const
{
    zmq_assert (status_code.length () == 3);
274
    const int rc = msg_->init_size (6 + 1 + status_code.length ());
275 276 277
    zmq_assert (rc == 0);
    char *msg_data = static_cast <char *> (msg_->data ());
    memcpy (msg_data, "\5ERROR", 6);
278
    msg_data [6] = (char) status_code.length ();
279
    memcpy (msg_data + 7, status_code.c_str (), status_code.length ());
280 281 282
    return 0;
}

283 284
void zmq::plain_server_t::send_zap_request (const std::string &username,
                                            const std::string &password)
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
{
    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);
    errno_assert (rc == 0);

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

304
    //  Request id frame
305 306 307 308 309 310 311 312
    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);
    errno_assert (rc == 0);

    //  Domain frame
313
    rc = msg.init_size (options.zap_domain.length ());
314
    errno_assert (rc == 0);
315
    memcpy (msg.data (), options.zap_domain.c_str (), options.zap_domain.length ());
316 317 318 319
    msg.set_flags (msg_t::more);
    rc = session->write_zap_msg (&msg);
    errno_assert (rc == 0);

320 321 322 323 324 325 326 327
    //  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);
    errno_assert (rc == 0);

328
    //  Identity frame
329
    rc = msg.init_size (options.identity_size);
330
    errno_assert (rc == 0);
331 332 333 334 335
    memcpy (msg.data (), options.identity, options.identity_size);
    msg.set_flags (msg_t::more);
    rc = session->write_zap_msg (&msg);
    errno_assert (rc == 0);

336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
    //  Mechanism frame
    rc = msg.init_size (5);
    errno_assert (rc == 0);
    memcpy (msg.data (), "PLAIN", 5);
    msg.set_flags (msg_t::more);
    rc = session->write_zap_msg (&msg);
    errno_assert (rc == 0);

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

    //  Password frame
    rc = msg.init_size (password.length ());
    errno_assert (rc == 0);
    memcpy (msg.data (), password.c_str (), password.length ());
    rc = session->write_zap_msg (&msg);
    errno_assert (rc == 0);
}

360
int zmq::plain_server_t::receive_and_process_zap_reply ()
361 362
{
    int rc = 0;
363
    msg_t msg [7];  //  ZAP reply consists of 7 frames
364

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

371
    for (int i = 0; i < 7; i++) {
372 373 374
        rc = session->read_zap_msg (&msg [i]);
        if (rc == -1)
            break;
375
        if ((msg [i].flags () & msg_t::more) == (i < 6? 0: msg_t::more)) {
376 377
            //  Temporary support for security debugging
            puts ("PLAIN I: ZAP handler sent incomplete reply message");
378 379 380 381 382 383 384 385 386 387 388
            errno = EPROTO;
            rc = -1;
            break;
        }
    }

    if (rc != 0)
        goto error;

    //  Address delimiter frame
    if (msg [0].size () > 0) {
389 390
        //  Temporary support for security debugging
        puts ("PLAIN I: ZAP handler sent malformed reply message");
391
        errno = EPROTO;
392
        rc = -1;
393 394 395 396 397
        goto error;
    }

    //  Version frame
    if (msg [1].size () != 3 || memcmp (msg [1].data (), "1.0", 3)) {
398 399
        //  Temporary support for security debugging
        puts ("PLAIN I: ZAP handler sent bad version number");
400
        errno = EPROTO;
401
        rc = -1;
402 403 404
        goto error;
    }

405
    //  Request id frame
406
    if (msg [2].size () != 1 || memcmp (msg [2].data (), "1", 1)) {
407 408
        //  Temporary support for security debugging
        puts ("PLAIN I: ZAP handler sent bad request ID");
409
        rc = -1;
410 411 412 413 414
        errno = EPROTO;
        goto error;
    }

    //  Status code frame
415
    if (msg [3].size () != 3) {
416 417
        //  Temporary support for security debugging
        puts ("PLAIN I: ZAP handler rejected client authentication");
418
        errno = EACCES;
419
        rc = -1;
420 421 422
        goto error;
    }

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

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

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

433
error:
434
    for (int i = 0; i < 7; i++) {
435 436 437 438 439 440
        const int rc2 = msg [i].close ();
        errno_assert (rc2 == 0);
    }

    return rc;
}