/* Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file This file is part of 0MQ. 0MQ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. 0MQ 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 . */ #include #include #include "testutil.hpp" static void * zap_handler (void *zap) { int rc, more; size_t optlen; zmq_msg_t version, seqno, domain, mechanism, username, password; zmq_msg_t status_code, status_text, user_id; // Version rc = zmq_msg_init (&version); assert (rc == 0); rc = zmq_msg_recv (&version, zap, 0); assert (rc == 3 && memcmp (zmq_msg_data (&version), "1.0", 3) == 0); optlen = sizeof more; rc = zmq_getsockopt (zap, ZMQ_RCVMORE, &more, &optlen); assert (rc == 0 && more == 1); // Sequence number rc = zmq_msg_init (&seqno); assert (rc == 0); rc = zmq_msg_recv (&seqno, zap, 0); assert (rc != -1); optlen = sizeof more; rc = zmq_getsockopt (zap, ZMQ_RCVMORE, &more, &optlen); assert (rc == 0 && more == 1); // Domain rc = zmq_msg_init (&domain); assert (rc == 0); rc = zmq_msg_recv (&domain, zap, 0); assert (rc != -1); optlen = sizeof more; rc = zmq_getsockopt (zap, ZMQ_RCVMORE, &more, &optlen); assert (rc == 0 && more == 1); // Mechanism rc = zmq_msg_init (&mechanism); assert (rc == 0); rc = zmq_msg_recv (&mechanism, zap, 0); assert (rc == 5 && memcmp (zmq_msg_data (&mechanism), "PLAIN", 5) == 0); optlen = sizeof more; rc = zmq_getsockopt (zap, ZMQ_RCVMORE, &more, &optlen); assert (rc == 0 && more == 1); // Username rc = zmq_msg_init (&username); assert (rc == 0); rc = zmq_msg_recv (&username, zap, 0); bool username_ok = (rc == 5 && memcmp (zmq_msg_data (&username), "admin", 5) == 0); optlen = sizeof more; rc = zmq_getsockopt (zap, ZMQ_RCVMORE, &more, &optlen); assert (rc == 0 && more == 1); // Password rc = zmq_msg_init (&password); assert (rc == 0); rc = zmq_msg_recv (&password, zap, 0); optlen = sizeof more; rc = zmq_getsockopt (zap, ZMQ_RCVMORE, &more, &optlen); assert (rc == 0 && more == 0); bool password_ok = (rc == 8 && memcmp (zmq_msg_data (&password), "password", 8) == 0); rc = zmq_msg_send (&version, zap, ZMQ_SNDMORE); assert (rc == 3); rc = zmq_msg_send (&seqno, zap, ZMQ_SNDMORE); assert (rc != -1); rc = zmq_msg_init_size (&status_code, 3); assert (rc == 0); memcpy (zmq_msg_data (&status_code), username_ok && password_ok? "200": "400", 3); rc = zmq_msg_send (&status_code, zap, ZMQ_SNDMORE); assert (rc == 3); rc = zmq_msg_init (&status_text); assert (rc == 0); rc = zmq_msg_send (&status_text, zap, ZMQ_SNDMORE); assert (rc == 0); rc = zmq_msg_init (&user_id); assert (rc == 0); rc = zmq_msg_send (&user_id, zap, 0); assert (rc == 0); rc = zmq_msg_close (&domain); assert (rc == 0); rc = zmq_msg_close (&mechanism); assert (rc == 0); rc = zmq_msg_close (&username); assert (rc == 0); rc = zmq_msg_close (&password); assert (rc == 0); rc = zmq_close (zap); assert (rc == 0); return NULL; } int main (void) { void *ctx = zmq_ctx_new (); assert (ctx); // Server socket will accept connections void *server = zmq_socket (ctx, ZMQ_DEALER); assert (server); // Client socket that will try to connect to server void *client = zmq_socket (ctx, ZMQ_DEALER); assert (client); // Check NULL security configuration int rc; size_t optsize; int mechanism; int as_server; optsize = sizeof (int); rc = zmq_getsockopt (client, ZMQ_MECHANISM, &mechanism, &optsize); assert (rc == 0); assert (mechanism == ZMQ_NULL); rc = zmq_getsockopt (server, ZMQ_MECHANISM, &mechanism, &optsize); assert (rc == 0); assert (mechanism == ZMQ_NULL); rc = zmq_getsockopt (client, ZMQ_PLAIN_SERVER, &as_server, &optsize); assert (rc == 0); assert (as_server == 0); rc = zmq_getsockopt (server, ZMQ_PLAIN_SERVER, &as_server, &optsize); assert (rc == 0); assert (as_server == 0); rc = zmq_bind (server, "tcp://*:9999"); assert (rc == 0); rc = zmq_connect (client, "tcp://localhost:9999"); assert (rc == 0); bounce (server, client); rc = zmq_close (client); assert (rc == 0); rc = zmq_close (server); assert (rc == 0); // Check PLAIN security server = zmq_socket (ctx, ZMQ_DEALER); assert (server); client = zmq_socket (ctx, ZMQ_DEALER); assert (client); char username [256]; optsize = 256; rc = zmq_getsockopt (client, ZMQ_PLAIN_USERNAME, username, &optsize); assert (rc == 0); assert (optsize == 1); // Null string is one byte long char password [256]; optsize = 256; rc = zmq_getsockopt (client, ZMQ_PLAIN_PASSWORD, password, &optsize); assert (rc == 0); assert (optsize == 1); // Null string is one byte long strcpy (username, "admin"); strcpy (password, "password"); rc = zmq_setsockopt (client, ZMQ_PLAIN_USERNAME, username, strlen (username)); assert (rc == 0); rc = zmq_setsockopt (client, ZMQ_PLAIN_PASSWORD, password, strlen (password)); assert (rc == 0); optsize = 256; rc = zmq_getsockopt (client, ZMQ_PLAIN_USERNAME, username, &optsize); assert (rc == 0); assert (optsize == 5 + 1); optsize = 256; rc = zmq_getsockopt (client, ZMQ_PLAIN_PASSWORD, password, &optsize); assert (rc == 0); assert (optsize == 8 + 1); as_server = 1; rc = zmq_setsockopt (server, ZMQ_PLAIN_SERVER, &as_server, sizeof (int)); assert (rc == 0); optsize = sizeof (int); rc = zmq_getsockopt (client, ZMQ_MECHANISM, &mechanism, &optsize); assert (rc == 0); assert (mechanism == ZMQ_PLAIN); rc = zmq_getsockopt (server, ZMQ_MECHANISM, &mechanism, &optsize); assert (rc == 0); assert (mechanism == ZMQ_PLAIN); rc = zmq_getsockopt (client, ZMQ_PLAIN_SERVER, &as_server, &optsize); assert (rc == 0); assert (as_server == 0); rc = zmq_getsockopt (server, ZMQ_PLAIN_SERVER, &as_server, &optsize); assert (rc == 0); assert (as_server == 1); // Create and bind ZAP socket void *zap = zmq_socket (ctx, ZMQ_REP); assert (zap); rc = zmq_bind (zap, "inproc://zeromq.zap.01"); assert (rc == 0); // Spawn ZAP handler pthread_t zap_thread; rc = pthread_create (&zap_thread, NULL, &zap_handler, zap); assert (rc == 0); rc = zmq_bind (server, "tcp://*:9998"); assert (rc == 0); rc = zmq_connect (client, "tcp://localhost:9998"); assert (rc == 0); bounce (server, client); rc = zmq_close (client); assert (rc == 0); rc = zmq_close (server); assert (rc == 0); // Wait until ZAP handler terminates. pthread_join (zap_thread, NULL); // Check PLAIN security -- two servers trying to talk to each other server = zmq_socket (ctx, ZMQ_DEALER); assert (server); client = zmq_socket (ctx, ZMQ_DEALER); assert (client); rc = zmq_setsockopt (server, ZMQ_PLAIN_SERVER, &as_server, sizeof (int)); assert (rc == 0); rc = zmq_setsockopt (client, ZMQ_PLAIN_SERVER, &as_server, sizeof (int)); assert (rc == 0); rc = zmq_bind (server, "tcp://*:9997"); assert (rc == 0); rc = zmq_connect (client, "tcp://localhost:9997"); assert (rc == 0); //TODO: this test fails without any error // bounce (server, client); rc = zmq_close (client); assert (rc == 0); rc = zmq_close (server); assert (rc == 0); // Shutdown rc = zmq_ctx_term (ctx); assert (rc == 0); return 0; }