LCOV - code coverage report
Current view: top level - home/h/core/forks/m4-libzmq/src - null_mechanism.cpp (source / functions) Hit Total Coverage
Test: zeromq-4.2.0 Code Coverage Lines: 146 179 81.6 %
Date: 2016-05-09 Functions: 10 11 90.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :     Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
       3             : 
       4             :     This file is part of libzmq, the ZeroMQ core engine in C++.
       5             : 
       6             :     libzmq is free software; you can redistribute it and/or modify it under
       7             :     the terms of the GNU Lesser General Public License (LGPL) as published
       8             :     by the Free Software Foundation; either version 3 of the License, or
       9             :     (at your option) any later version.
      10             : 
      11             :     As a special exception, the Contributors give you permission to link
      12             :     this library with independent modules to produce an executable,
      13             :     regardless of the license terms of these independent modules, and to
      14             :     copy and distribute the resulting executable under terms of your choice,
      15             :     provided that you also meet, for each linked independent module, the
      16             :     terms and conditions of the license of that module. An independent
      17             :     module is a module which is not derived from or based on this library.
      18             :     If you modify this library, you must extend this exception to your
      19             :     version of the library.
      20             : 
      21             :     libzmq is distributed in the hope that it will be useful, but WITHOUT
      22             :     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      23             :     FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
      24             :     License for more details.
      25             : 
      26             :     You should have received a copy of the GNU Lesser General Public License
      27             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      28             : */
      29             : 
      30             : #include "precompiled.hpp"
      31             : #include "platform.hpp"
      32             : #ifdef ZMQ_HAVE_WINDOWS
      33             : #include "windows.hpp"
      34             : #endif
      35             : 
      36             : #include <stddef.h>
      37             : #include <string.h>
      38             : #include <stdlib.h>
      39             : 
      40             : #include "err.hpp"
      41             : #include "msg.hpp"
      42             : #include "session_base.hpp"
      43             : #include "wire.hpp"
      44             : #include "null_mechanism.hpp"
      45             : 
      46        4209 : zmq::null_mechanism_t::null_mechanism_t (session_base_t *session_,
      47             :                                          const std::string &peer_address_,
      48             :                                          const options_t &options_) :
      49             :     mechanism_t (options_),
      50             :     session (session_),
      51             :     peer_address (peer_address_),
      52             :     ready_command_sent (false),
      53             :     error_command_sent (false),
      54             :     ready_command_received (false),
      55             :     error_command_received (false),
      56             :     zap_connected (false),
      57             :     zap_request_sent (false),
      58        4209 :     zap_reply_received (false)
      59             : {
      60             :     //  NULL mechanism only uses ZAP if there's a domain defined
      61             :     //  This prevents ZAP requests on naive sockets
      62        8418 :     if (options.zap_domain.size () > 0
      63        4209 :     &&  session->zap_connect () == 0)
      64           9 :         zap_connected = true;
      65        4209 : }
      66             : 
      67       12627 : zmq::null_mechanism_t::~null_mechanism_t ()
      68             : {
      69        8418 : }
      70             : 
      71        8826 : int zmq::null_mechanism_t::next_handshake_command (msg_t *msg_)
      72             : {
      73        8826 :     if (ready_command_sent || error_command_sent) {
      74        4787 :         errno = EAGAIN;
      75        4787 :         return -1;
      76             :     }
      77        4039 :     if (zap_connected && !zap_reply_received) {
      78          18 :         if (zap_request_sent) {
      79           9 :             errno = EAGAIN;
      80           9 :             return -1;
      81             :         }
      82           9 :         send_zap_request ();
      83           9 :         zap_request_sent = true;
      84           9 :         const int rc = receive_and_process_zap_reply ();
      85           9 :         if (rc != 0)
      86             :             return -1;
      87           0 :         zap_reply_received = true;
      88             :     }
      89             : 
      90        4021 :     if (zap_reply_received
      91           9 :     &&  strncmp (status_code, "200", sizeof status_code) != 0) {
      92           3 :         const int rc = msg_->init_size (6 + 1 + sizeof status_code);
      93           3 :         zmq_assert (rc == 0);
      94             :         unsigned char *msg_data =
      95           3 :             static_cast <unsigned char *> (msg_->data ());
      96             :         memcpy (msg_data, "\5ERROR", 6);
      97           3 :         msg_data [6] = sizeof status_code;
      98           3 :         memcpy (msg_data + 7, status_code, sizeof status_code);
      99           3 :         error_command_sent = true;
     100           3 :         return 0;
     101             :     }
     102             : 
     103        4018 :     unsigned char *const command_buffer = (unsigned char *) malloc (512);
     104        4018 :     alloc_assert (command_buffer);
     105             : 
     106        4018 :     unsigned char *ptr = command_buffer;
     107             : 
     108             :     //  Add mechanism string
     109             :     memcpy (ptr, "\5READY", 6);
     110        4018 :     ptr += 6;
     111             : 
     112             :     //  Add socket type property
     113        4018 :     const char *socket_type = socket_type_string (options.type);
     114        4018 :     ptr += add_property (ptr, "Socket-Type", socket_type, strlen (socket_type));
     115             : 
     116             :     //  Add identity property
     117        4018 :     if (options.type == ZMQ_REQ
     118        4018 :     ||  options.type == ZMQ_DEALER
     119        4018 :     ||  options.type == ZMQ_ROUTER)
     120         957 :         ptr += add_property (ptr, "Identity", options.identity, options.identity_size);
     121             : 
     122        4018 :     const size_t command_size = ptr - command_buffer;
     123        4018 :     const int rc = msg_->init_size (command_size);
     124        4018 :     errno_assert (rc == 0);
     125        4018 :     memcpy (msg_->data (), command_buffer, command_size);
     126        4018 :     free (command_buffer);
     127             : 
     128        4018 :     ready_command_sent = true;
     129             : 
     130        4018 :     return 0;
     131             : }
     132             : 
     133        3864 : int zmq::null_mechanism_t::process_handshake_command (msg_t *msg_)
     134             : {
     135        3864 :     if (ready_command_received || error_command_received) {
     136             :         //  Temporary support for security debugging
     137           0 :         puts ("NULL I: client sent invalid NULL handshake (duplicate READY)");
     138           0 :         errno = EPROTO;
     139           0 :         return -1;
     140             :     }
     141             : 
     142             :     const unsigned char *cmd_data =
     143        3864 :         static_cast <unsigned char *> (msg_->data ());
     144        3864 :     const size_t data_size = msg_->size ();
     145             : 
     146        3864 :     int rc = 0;
     147        3864 :     if (data_size >= 6 && !memcmp (cmd_data, "\5READY", 6))
     148        3860 :         rc = process_ready_command (cmd_data, data_size);
     149             :     else
     150           4 :     if (data_size >= 6 && !memcmp (cmd_data, "\5ERROR", 6))
     151           3 :         rc = process_error_command (cmd_data, data_size);
     152             :     else {
     153             :         //  Temporary support for security debugging
     154           1 :         puts ("NULL I: client sent invalid NULL handshake (not READY)");
     155           0 :         errno = EPROTO;
     156           0 :         rc = -1;
     157             :     }
     158             : 
     159        3864 :     if (rc == 0) {
     160        3864 :         rc = msg_->close ();
     161        3864 :         errno_assert (rc == 0);
     162        3864 :         rc = msg_->init ();
     163        3864 :         errno_assert (rc == 0);
     164             :     }
     165        3864 :     return rc;
     166             : }
     167             : 
     168           0 : int zmq::null_mechanism_t::process_ready_command (
     169             :         const unsigned char *cmd_data, size_t data_size)
     170             : {
     171        3860 :     ready_command_received = true;
     172        3860 :     return parse_metadata (cmd_data + 6, data_size - 6);
     173             : }
     174             : 
     175           3 : int zmq::null_mechanism_t::process_error_command (
     176             :         const unsigned char *cmd_data, size_t data_size)
     177             : {
     178           3 :     if (data_size < 7) {
     179           0 :         errno = EPROTO;
     180           0 :         return -1;
     181             :     }
     182           3 :     const size_t error_reason_len = static_cast <size_t> (cmd_data [6]);
     183           3 :     if (error_reason_len > data_size - 7) {
     184           0 :         errno = EPROTO;
     185           0 :         return -1;
     186             :     }
     187           3 :     error_command_received = true;
     188           3 :     return 0;
     189             : }
     190             : 
     191           9 : int zmq::null_mechanism_t::zap_msg_available ()
     192             : {
     193           9 :     if (zap_reply_received) {
     194           0 :         errno = EFSM;
     195           0 :         return -1;
     196             :     }
     197           9 :     const int rc = receive_and_process_zap_reply ();
     198           9 :     if (rc == 0)
     199           9 :         zap_reply_received = true;
     200           9 :     return rc;
     201             : }
     202             : 
     203       24770 : zmq::mechanism_t::status_t zmq::null_mechanism_t::status () const
     204             : {
     205             :     const bool command_sent =
     206       24770 :         ready_command_sent || error_command_sent;
     207             :     const bool command_received =
     208       24770 :         ready_command_received || error_command_received;
     209             : 
     210       24770 :     if (ready_command_sent && ready_command_received)
     211             :         return ready;
     212             :     else
     213       21024 :     if (command_sent && command_received)
     214             :         return error;
     215             :     else
     216       21006 :         return handshaking;
     217             : }
     218             : 
     219           9 : void zmq::null_mechanism_t::send_zap_request ()
     220             : {
     221             :     int rc;
     222             :     msg_t msg;
     223             : 
     224             :     //  Address delimiter frame
     225           9 :     rc = msg.init ();
     226           9 :     errno_assert (rc == 0);
     227           9 :     msg.set_flags (msg_t::more);
     228           9 :     rc = session->write_zap_msg (&msg);
     229           9 :     errno_assert (rc == 0);
     230             : 
     231             :     //  Version frame
     232           9 :     rc = msg.init_size (3);
     233           9 :     errno_assert (rc == 0);
     234           9 :     memcpy (msg.data (), "1.0", 3);
     235           9 :     msg.set_flags (msg_t::more);
     236           9 :     rc = session->write_zap_msg (&msg);
     237           9 :     errno_assert (rc == 0);
     238             : 
     239             :     //  Request id frame
     240           9 :     rc = msg.init_size (1);
     241           9 :     errno_assert (rc == 0);
     242           9 :     memcpy (msg.data (), "1", 1);
     243           9 :     msg.set_flags (msg_t::more);
     244           9 :     rc = session->write_zap_msg (&msg);
     245           9 :     errno_assert (rc == 0);
     246             : 
     247             :     //  Domain frame
     248          18 :     rc = msg.init_size (options.zap_domain.length ());
     249           9 :     errno_assert (rc == 0);
     250          18 :     memcpy (msg.data (), options.zap_domain.c_str (), options.zap_domain.length ());
     251           9 :     msg.set_flags (msg_t::more);
     252           9 :     rc = session->write_zap_msg (&msg);
     253           9 :     errno_assert (rc == 0);
     254             : 
     255             :     //  Address frame
     256          18 :     rc = msg.init_size (peer_address.length ());
     257           9 :     errno_assert (rc == 0);
     258          18 :     memcpy (msg.data (), peer_address.c_str (), peer_address.length ());
     259           9 :     msg.set_flags (msg_t::more);
     260           9 :     rc = session->write_zap_msg (&msg);
     261           9 :     errno_assert (rc == 0);
     262             : 
     263             :     //  Identity frame
     264           9 :     rc = msg.init_size (options.identity_size);
     265           9 :     errno_assert (rc == 0);
     266           9 :     memcpy (msg.data (), options.identity, options.identity_size);
     267           9 :     msg.set_flags (msg_t::more);
     268           9 :     rc = session->write_zap_msg (&msg);
     269           9 :     errno_assert (rc == 0);
     270             : 
     271             :     //  Mechanism frame
     272           9 :     rc = msg.init_size (4);
     273           9 :     errno_assert (rc == 0);
     274           9 :     memcpy (msg.data (), "NULL", 4);
     275           9 :     rc = session->write_zap_msg (&msg);
     276           9 :     errno_assert (rc == 0);
     277           9 : }
     278             : 
     279          18 : int zmq::null_mechanism_t::receive_and_process_zap_reply ()
     280             : {
     281          18 :     int rc = 0;
     282             :     msg_t msg [7];  //  ZAP reply consists of 7 frames
     283             : 
     284             :     //  Initialize all reply frames
     285         144 :     for (int i = 0; i < 7; i++) {
     286         126 :         rc = msg [i].init ();
     287         126 :         errno_assert (rc == 0);
     288             :     }
     289             : 
     290          63 :     for (int i = 0; i < 7; i++) {
     291          72 :         rc = session->read_zap_msg (&msg [i]);
     292          72 :         if (rc == -1)
     293             :             break;
     294          63 :         if ((msg [i].flags () & msg_t::more) == (i < 6? 0: msg_t::more)) {
     295             :             //  Temporary support for security debugging
     296           0 :             puts ("NULL I: ZAP handler sent incomplete reply message");
     297           0 :             errno = EPROTO;
     298           0 :             rc = -1;
     299           0 :             break;
     300             :         }
     301             :     }
     302             : 
     303          18 :     if (rc != 0)
     304             :         goto error;
     305             : 
     306             :     //  Address delimiter frame
     307           9 :     if (msg [0].size () > 0) {
     308             :         //  Temporary support for security debugging
     309           0 :         puts ("NULL I: ZAP handler sent malformed reply message");
     310           0 :         errno = EPROTO;
     311           0 :         rc = -1;
     312           0 :         goto error;
     313             :     }
     314             : 
     315             :     //  Version frame
     316           9 :     if (msg [1].size () != 3 || memcmp (msg [1].data (), "1.0", 3)) {
     317             :         //  Temporary support for security debugging
     318           0 :         puts ("NULL I: ZAP handler sent bad version number");
     319           0 :         errno = EPROTO;
     320           0 :         rc = -1;
     321           0 :         goto error;
     322             :     }
     323             : 
     324             :     //  Request id frame
     325           9 :     if (msg [2].size () != 1 || memcmp (msg [2].data (), "1", 1)) {
     326             :         //  Temporary support for security debugging
     327           0 :         puts ("NULL I: ZAP handler sent bad request ID");
     328           0 :         errno = EPROTO;
     329           0 :         rc = -1;
     330           0 :         goto error;
     331             :     }
     332             : 
     333             :     //  Status code frame
     334           9 :     if (msg [3].size () != 3) {
     335             :         //  Temporary support for security debugging
     336           0 :         puts ("NULL I: ZAP handler rejected client authentication");
     337           0 :         errno = EPROTO;
     338           0 :         rc = -1;
     339           0 :         goto error;
     340             :     }
     341             : 
     342             :     //  Save status code
     343           9 :     memcpy (status_code, msg [3].data (), sizeof status_code);
     344             : 
     345             :     //  Save user id
     346           9 :     set_user_id (msg [5].data (), msg [5].size ());
     347             : 
     348             :     //  Process metadata frame
     349           9 :     rc = parse_metadata (static_cast <const unsigned char*> (msg [6].data ()),
     350          18 :                          msg [6].size (), true);
     351             : 
     352             : error:
     353         144 :     for (int i = 0; i < 7; i++) {
     354         126 :         const int rc2 = msg [i].close ();
     355         126 :         errno_assert (rc2 == 0);
     356             :     }
     357             : 
     358          18 :     return rc;
     359             : }

Generated by: LCOV version 1.10