LCOV - code coverage report
Current view: top level - home/h/core/forks/m4-libzmq/src - curve_server.cpp (source / functions) Hit Total Coverage
Test: zeromq-4.2.0 Code Coverage Lines: 276 341 80.9 %
Date: 2016-05-09 Functions: 16 16 100.0 %
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 "macros.hpp"
      32             : #include "platform.hpp"
      33             : 
      34             : #ifdef ZMQ_HAVE_CURVE
      35             : 
      36             : #ifdef ZMQ_HAVE_WINDOWS
      37             : #include "windows.hpp"
      38             : #endif
      39             : 
      40             : #include "msg.hpp"
      41             : #include "session_base.hpp"
      42             : #include "err.hpp"
      43             : #include "curve_server.hpp"
      44             : #include "wire.hpp"
      45             : 
      46          45 : zmq::curve_server_t::curve_server_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             :     state (expect_hello),
      53             :     cn_nonce (1),
      54          90 :     cn_peer_nonce(1)
      55             : {
      56             :     int rc;
      57             :     //  Fetch our secret key from socket options
      58          45 :     memcpy (secret_key, options_.curve_secret_key, crypto_box_SECRETKEYBYTES);
      59             : 
      60             :     //  Generate short-term key pair
      61          45 :     rc = crypto_box_keypair (cn_public, cn_secret);
      62          45 :     zmq_assert (rc == 0);
      63          45 : }
      64             : 
      65         180 : zmq::curve_server_t::~curve_server_t ()
      66             : {
      67          90 : }
      68             : 
      69         159 : int zmq::curve_server_t::next_handshake_command (msg_t *msg_)
      70             : {
      71         159 :     int rc = 0;
      72             : 
      73         159 :     switch (state) {
      74             :         case send_welcome:
      75          33 :             rc = produce_welcome (msg_);
      76          33 :             if (rc == 0)
      77          33 :                 state = expect_initiate;
      78             :             break;
      79             :         case send_ready:
      80           6 :             rc = produce_ready (msg_);
      81           6 :             if (rc == 0)
      82           6 :                 state = connected;
      83             :             break;
      84             :         case send_error:
      85           3 :             rc = produce_error (msg_);
      86           3 :             if (rc == 0)
      87           3 :                 state = error_sent;
      88             :             break;
      89             :         default:
      90         117 :             errno = EAGAIN;
      91         117 :             rc = -1;
      92         117 :             break;
      93             :     }
      94         159 :     return rc;
      95             : }
      96             : 
      97          78 : int zmq::curve_server_t::process_handshake_command (msg_t *msg_)
      98             : {
      99          78 :     int rc = 0;
     100             : 
     101          78 :     switch (state) {
     102             :         case expect_hello:
     103          45 :             rc = process_hello (msg_);
     104          45 :             break;
     105             :         case expect_initiate:
     106          33 :             rc = process_initiate (msg_);
     107          33 :             break;
     108             :         default:
     109             :             //  Temporary support for security debugging
     110           0 :             puts ("CURVE I: invalid handshake command");
     111           0 :             errno = EPROTO;
     112           0 :             rc = -1;
     113           0 :             break;
     114             :     }
     115          78 :     if (rc == 0) {
     116          42 :         rc = msg_->close ();
     117          42 :         errno_assert (rc == 0);
     118          42 :         rc = msg_->init ();
     119          42 :         errno_assert (rc == 0);
     120             :     }
     121          78 :     return rc;
     122             : }
     123             : 
     124          57 : int zmq::curve_server_t::encode (msg_t *msg_)
     125             : {
     126          57 :     zmq_assert (state == connected);
     127             : 
     128          57 :     const size_t mlen = crypto_box_ZEROBYTES + 1 + msg_->size ();
     129             : 
     130             :     uint8_t message_nonce [crypto_box_NONCEBYTES];
     131             :     memcpy (message_nonce, "CurveZMQMESSAGES", 16);
     132          57 :     put_uint64 (message_nonce + 16, cn_nonce);
     133             : 
     134          57 :     uint8_t flags = 0;
     135          57 :     if (msg_->flags () & msg_t::more)
     136           3 :         flags |= 0x01;
     137          57 :     if (msg_->flags () & msg_t::command)
     138          51 :         flags |= 0x02;
     139             : 
     140          57 :     uint8_t *message_plaintext = static_cast <uint8_t *> (malloc (mlen));
     141          57 :     alloc_assert (message_plaintext);
     142             : 
     143             :     memset (message_plaintext, 0, crypto_box_ZEROBYTES);
     144          57 :     message_plaintext [crypto_box_ZEROBYTES] = flags;
     145          57 :     memcpy (message_plaintext + crypto_box_ZEROBYTES + 1,
     146          57 :             msg_->data (), msg_->size ());
     147             : 
     148          57 :     uint8_t *message_box = static_cast <uint8_t *> (malloc (mlen));
     149          57 :     alloc_assert (message_box);
     150             : 
     151             :     int rc = crypto_box_afternm (message_box, message_plaintext,
     152          57 :                                  mlen, message_nonce, cn_precom);
     153          57 :     zmq_assert (rc == 0);
     154             : 
     155          57 :     rc = msg_->close ();
     156          57 :     zmq_assert (rc == 0);
     157             : 
     158          57 :     rc = msg_->init_size (16 + mlen - crypto_box_BOXZEROBYTES);
     159          57 :     zmq_assert (rc == 0);
     160             : 
     161          57 :     uint8_t *message = static_cast <uint8_t *> (msg_->data ());
     162             : 
     163             :     memcpy (message, "\x07MESSAGE", 8);
     164          57 :     memcpy (message + 8, message_nonce + 16, 8);
     165          57 :     memcpy (message + 16, message_box + crypto_box_BOXZEROBYTES,
     166          57 :             mlen - crypto_box_BOXZEROBYTES);
     167             : 
     168          57 :     free (message_plaintext);
     169          57 :     free (message_box);
     170             : 
     171          57 :     cn_nonce++;
     172             : 
     173          57 :     return 0;
     174             : }
     175             : 
     176          57 : int zmq::curve_server_t::decode (msg_t *msg_)
     177             : {
     178          57 :     zmq_assert (state == connected);
     179             : 
     180          57 :     if (msg_->size () < 33) {
     181             :         //  Temporary support for security debugging
     182           0 :         puts ("CURVE I: invalid CURVE client, sent malformed command");
     183           0 :         errno = EPROTO;
     184           0 :         return -1;
     185             :     }
     186             : 
     187          57 :     const uint8_t *message = static_cast <uint8_t *> (msg_->data ());
     188          57 :     if (memcmp (message, "\x07MESSAGE", 8)) {
     189             :         //  Temporary support for security debugging
     190           0 :         puts ("CURVE I: invalid CURVE client, did not send MESSAGE");
     191           0 :         errno = EPROTO;
     192           0 :         return -1;
     193             :     }
     194             : 
     195             :     uint8_t message_nonce [crypto_box_NONCEBYTES];
     196             :     memcpy (message_nonce, "CurveZMQMESSAGEC", 16);
     197          57 :     memcpy (message_nonce + 16, message + 8, 8);
     198          57 :     uint64_t nonce = get_uint64(message + 8);
     199          57 :     if (nonce <= cn_peer_nonce) {
     200           0 :         errno = EPROTO;
     201           0 :         return -1;
     202             :     }
     203          57 :     cn_peer_nonce = nonce;
     204             : 
     205          57 :     const size_t clen = crypto_box_BOXZEROBYTES + msg_->size () - 16;
     206             : 
     207          57 :     uint8_t *message_plaintext = static_cast <uint8_t *> (malloc (clen));
     208          57 :     alloc_assert (message_plaintext);
     209             : 
     210          57 :     uint8_t *message_box = static_cast <uint8_t *> (malloc (clen));
     211          57 :     alloc_assert (message_box);
     212             : 
     213             :     memset (message_box, 0, crypto_box_BOXZEROBYTES);
     214          57 :     memcpy (message_box + crypto_box_BOXZEROBYTES,
     215          57 :             message + 16, msg_->size () - 16);
     216             : 
     217             :     int rc = crypto_box_open_afternm (message_plaintext, message_box,
     218          57 :                                       clen, message_nonce, cn_precom);
     219          57 :     if (rc == 0) {
     220          57 :         rc = msg_->close ();
     221          57 :         zmq_assert (rc == 0);
     222             : 
     223          57 :         rc = msg_->init_size (clen - 1 - crypto_box_ZEROBYTES);
     224          57 :         zmq_assert (rc == 0);
     225             : 
     226          57 :         const uint8_t flags = message_plaintext [crypto_box_ZEROBYTES];
     227          57 :         if (flags & 0x01)
     228           3 :             msg_->set_flags (msg_t::more);
     229          57 :         if (flags & 0x02)
     230          51 :             msg_->set_flags (msg_t::command);
     231             : 
     232             :         memcpy (msg_->data (),
     233             :                 message_plaintext + crypto_box_ZEROBYTES + 1,
     234          57 :                 msg_->size ());
     235             :     }
     236             :     else {
     237             :         //  Temporary support for security debugging
     238           0 :         puts ("CURVE I: connection key used for MESSAGE is wrong");
     239           0 :         errno = EPROTO;
     240             :     }
     241          57 :     free (message_plaintext);
     242          57 :     free (message_box);
     243             : 
     244          57 :     return rc;
     245             : }
     246             : 
     247           6 : int zmq::curve_server_t::zap_msg_available ()
     248             : {
     249           6 :     if (state != expect_zap_reply) {
     250           0 :         errno = EFSM;
     251           0 :         return -1;
     252             :     }
     253           6 :     const int rc = receive_and_process_zap_reply ();
     254           6 :     if (rc == 0)
     255           6 :         state = status_code == "200"
     256             :             ? send_ready
     257           6 :             : send_error;
     258           6 :     return rc;
     259             : }
     260             : 
     261         420 : zmq::mechanism_t::status_t zmq::curve_server_t::status () const
     262             : {
     263         420 :     if (state == connected)
     264             :         return mechanism_t::ready;
     265             :     else
     266         414 :     if (state == error_sent)
     267             :         return mechanism_t::error;
     268             :     else
     269         402 :         return mechanism_t::handshaking;
     270             : }
     271             : 
     272          45 : int zmq::curve_server_t::process_hello (msg_t *msg_)
     273             : {
     274          45 :     if (msg_->size () != 200) {
     275             :         //  Temporary support for security debugging
     276           0 :         puts ("CURVE I: client HELLO is not correct size");
     277           0 :         errno = EPROTO;
     278           0 :         return -1;
     279             :     }
     280             : 
     281          45 :     const uint8_t * const hello = static_cast <uint8_t *> (msg_->data ());
     282          45 :     if (memcmp (hello, "\x05HELLO", 6)) {
     283             :         //  Temporary support for security debugging
     284           0 :         puts ("CURVE I: client HELLO has invalid command name");
     285           0 :         errno = EPROTO;
     286           0 :         return -1;
     287             :     }
     288             : 
     289          45 :     const uint8_t major = hello [6];
     290          45 :     const uint8_t minor = hello [7];
     291             : 
     292          45 :     if (major != 1 || minor != 0) {
     293             :         //  Temporary support for security debugging
     294           0 :         puts ("CURVE I: client HELLO has unknown version number");
     295           0 :         errno = EPROTO;
     296           0 :         return -1;
     297             :     }
     298             : 
     299             :     //  Save client's short-term public key (C')
     300          45 :     memcpy (cn_client, hello + 80, 32);
     301             : 
     302             :     uint8_t hello_nonce [crypto_box_NONCEBYTES];
     303             :     uint8_t hello_plaintext [crypto_box_ZEROBYTES + 64];
     304             :     uint8_t hello_box [crypto_box_BOXZEROBYTES + 80];
     305             : 
     306             :     memcpy (hello_nonce, "CurveZMQHELLO---", 16);
     307          45 :     memcpy (hello_nonce + 16, hello + 112, 8);
     308          45 :     cn_peer_nonce = get_uint64(hello + 112);
     309             : 
     310             :     memset (hello_box, 0, crypto_box_BOXZEROBYTES);
     311          45 :     memcpy (hello_box + crypto_box_BOXZEROBYTES, hello + 120, 80);
     312             : 
     313             :     //  Open Box [64 * %x0](C'->S)
     314             :     int rc = crypto_box_open (hello_plaintext, hello_box,
     315             :                               sizeof hello_box,
     316          45 :                               hello_nonce, cn_client, secret_key);
     317          45 :     if (rc != 0) {
     318             :         //  Temporary support for security debugging
     319          12 :         puts ("CURVE I: cannot open client HELLO -- wrong server key?");
     320          12 :         errno = EPROTO;
     321          12 :         return -1;
     322             :     }
     323             : 
     324          33 :     state = send_welcome;
     325          33 :     return rc;
     326             : }
     327             : 
     328          33 : int zmq::curve_server_t::produce_welcome (msg_t *msg_)
     329             : {
     330             :     uint8_t cookie_nonce [crypto_secretbox_NONCEBYTES];
     331             :     uint8_t cookie_plaintext [crypto_secretbox_ZEROBYTES + 64];
     332             :     uint8_t cookie_ciphertext [crypto_secretbox_BOXZEROBYTES + 80];
     333             : 
     334             :     //  Create full nonce for encryption
     335             :     //  8-byte prefix plus 16-byte random nonce
     336             :     memcpy (cookie_nonce, "COOKIE--", 8);
     337          33 :     randombytes (cookie_nonce + 8, 16);
     338             : 
     339             :     //  Generate cookie = Box [C' + s'](t)
     340             :     memset (cookie_plaintext, 0, crypto_secretbox_ZEROBYTES);
     341             :     memcpy (cookie_plaintext + crypto_secretbox_ZEROBYTES,
     342          33 :             cn_client, 32);
     343             :     memcpy (cookie_plaintext + crypto_secretbox_ZEROBYTES + 32,
     344          33 :             cn_secret, 32);
     345             : 
     346             :     //  Generate fresh cookie key
     347          33 :     randombytes (cookie_key, crypto_secretbox_KEYBYTES);
     348             : 
     349             :     //  Encrypt using symmetric cookie key
     350             :     int rc = crypto_secretbox (cookie_ciphertext, cookie_plaintext,
     351             :                                sizeof cookie_plaintext,
     352          33 :                                cookie_nonce, cookie_key);
     353          33 :     zmq_assert (rc == 0);
     354             : 
     355             :     uint8_t welcome_nonce [crypto_box_NONCEBYTES];
     356             :     uint8_t welcome_plaintext [crypto_box_ZEROBYTES + 128];
     357             :     uint8_t welcome_ciphertext [crypto_box_BOXZEROBYTES + 144];
     358             : 
     359             :     //  Create full nonce for encryption
     360             :     //  8-byte prefix plus 16-byte random nonce
     361             :     memcpy (welcome_nonce, "WELCOME-", 8);
     362          33 :     randombytes (welcome_nonce + 8, crypto_box_NONCEBYTES - 8);
     363             : 
     364             :     //  Create 144-byte Box [S' + cookie](S->C')
     365             :     memset (welcome_plaintext, 0, crypto_box_ZEROBYTES);
     366          33 :     memcpy (welcome_plaintext + crypto_box_ZEROBYTES, cn_public, 32);
     367             :     memcpy (welcome_plaintext + crypto_box_ZEROBYTES + 32,
     368             :             cookie_nonce + 8, 16);
     369             :     memcpy (welcome_plaintext + crypto_box_ZEROBYTES + 48,
     370             :             cookie_ciphertext + crypto_secretbox_BOXZEROBYTES, 80);
     371             : 
     372             :     rc = crypto_box (welcome_ciphertext, welcome_plaintext,
     373             :                      sizeof welcome_plaintext,
     374          33 :                      welcome_nonce, cn_client, secret_key);
     375          33 :     if (rc == -1)
     376             :         return -1;
     377             : 
     378          33 :     rc = msg_->init_size (168);
     379          33 :     errno_assert (rc == 0);
     380             : 
     381          33 :     uint8_t * const welcome = static_cast <uint8_t *> (msg_->data ());
     382             :     memcpy (welcome, "\x07WELCOME", 8);
     383          33 :     memcpy (welcome + 8, welcome_nonce + 8, 16);
     384          33 :     memcpy (welcome + 24, welcome_ciphertext + crypto_box_BOXZEROBYTES, 144);
     385             : 
     386          33 :     return 0;
     387             : }
     388             : 
     389          33 : int zmq::curve_server_t::process_initiate (msg_t *msg_)
     390             : {
     391          33 :     if (msg_->size () < 257) {
     392             :         //  Temporary support for security debugging
     393           0 :         puts ("CURVE I: client INITIATE is not correct size");
     394           0 :         errno = EPROTO;
     395           0 :         return -1;
     396             :     }
     397             : 
     398          33 :     const uint8_t *initiate = static_cast <uint8_t *> (msg_->data ());
     399          33 :     if (memcmp (initiate, "\x08INITIATE", 9)) {
     400             :         //  Temporary support for security debugging
     401           0 :         puts ("CURVE I: client INITIATE has invalid command name");
     402           0 :         errno = EPROTO;
     403           0 :         return -1;
     404             :     }
     405             : 
     406             :     uint8_t cookie_nonce [crypto_secretbox_NONCEBYTES];
     407             :     uint8_t cookie_plaintext [crypto_secretbox_ZEROBYTES + 64];
     408             :     uint8_t cookie_box [crypto_secretbox_BOXZEROBYTES + 80];
     409             : 
     410             :     //  Open Box [C' + s'](t)
     411             :     memset (cookie_box, 0, crypto_secretbox_BOXZEROBYTES);
     412          33 :     memcpy (cookie_box + crypto_secretbox_BOXZEROBYTES, initiate + 25, 80);
     413             : 
     414             :     memcpy (cookie_nonce, "COOKIE--", 8);
     415          33 :     memcpy (cookie_nonce + 8, initiate + 9, 16);
     416             : 
     417             :     int rc = crypto_secretbox_open (cookie_plaintext, cookie_box,
     418             :                                     sizeof cookie_box,
     419          33 :                                     cookie_nonce, cookie_key);
     420          33 :     if (rc != 0) {
     421             :         //  Temporary support for security debugging
     422           0 :         puts ("CURVE I: cannot open client INITIATE cookie");
     423           0 :         errno = EPROTO;
     424           0 :         return -1;
     425             :     }
     426             : 
     427             :     //  Check cookie plain text is as expected [C' + s']
     428          33 :     if (memcmp (cookie_plaintext + crypto_secretbox_ZEROBYTES, cn_client, 32)
     429          33 :     ||  memcmp (cookie_plaintext + crypto_secretbox_ZEROBYTES + 32, cn_secret, 32)) {
     430             :         //  Temporary support for security debugging
     431           0 :         puts ("CURVE I: client INITIATE cookie is not valid");
     432           0 :         errno = EPROTO;
     433           0 :         return -1;
     434             :     }
     435             : 
     436          33 :     const size_t clen = (msg_->size () - 113) + crypto_box_BOXZEROBYTES;
     437             : 
     438             :     uint8_t initiate_nonce [crypto_box_NONCEBYTES];
     439             :     uint8_t initiate_plaintext [crypto_box_ZEROBYTES + 128 + 256];
     440             :     uint8_t initiate_box [crypto_box_BOXZEROBYTES + 144 + 256];
     441             : 
     442             :     //  Open Box [C + vouch + metadata](C'->S')
     443             :     memset (initiate_box, 0, crypto_box_BOXZEROBYTES);
     444             :     memcpy (initiate_box + crypto_box_BOXZEROBYTES,
     445          33 :             initiate + 113, clen - crypto_box_BOXZEROBYTES);
     446             : 
     447             :     memcpy (initiate_nonce, "CurveZMQINITIATE", 16);
     448          33 :     memcpy (initiate_nonce + 16, initiate + 105, 8);
     449          33 :     cn_peer_nonce = get_uint64(initiate + 105);
     450             : 
     451             :     rc = crypto_box_open (initiate_plaintext, initiate_box,
     452          33 :                           clen, initiate_nonce, cn_client, cn_secret);
     453          33 :     if (rc != 0) {
     454             :         //  Temporary support for security debugging
     455           0 :         puts ("CURVE I: cannot open client INITIATE");
     456           0 :         errno = EPROTO;
     457           0 :         return -1;
     458             :     }
     459             : 
     460          33 :     const uint8_t *client_key = initiate_plaintext + crypto_box_ZEROBYTES;
     461             : 
     462             :     uint8_t vouch_nonce [crypto_box_NONCEBYTES];
     463             :     uint8_t vouch_plaintext [crypto_box_ZEROBYTES + 64];
     464             :     uint8_t vouch_box [crypto_box_BOXZEROBYTES + 80];
     465             : 
     466             :     //  Open Box Box [C',S](C->S') and check contents
     467             :     memset (vouch_box, 0, crypto_box_BOXZEROBYTES);
     468             :     memcpy (vouch_box + crypto_box_BOXZEROBYTES,
     469             :             initiate_plaintext + crypto_box_ZEROBYTES + 48, 80);
     470             : 
     471             :     memcpy (vouch_nonce, "VOUCH---", 8);
     472             :     memcpy (vouch_nonce + 8,
     473             :             initiate_plaintext + crypto_box_ZEROBYTES + 32, 16);
     474             : 
     475             :     rc = crypto_box_open (vouch_plaintext, vouch_box,
     476             :                           sizeof vouch_box,
     477          33 :                           vouch_nonce, client_key, cn_secret);
     478          33 :     if (rc != 0) {
     479             :         //  Temporary support for security debugging
     480          24 :         puts ("CURVE I: cannot open client INITIATE vouch");
     481          24 :         errno = EPROTO;
     482          24 :         return -1;
     483             :     }
     484             : 
     485             :     //  What we decrypted must be the client's short-term public key
     486           9 :     if (memcmp (vouch_plaintext + crypto_box_ZEROBYTES, cn_client, 32)) {
     487             :         //  Temporary support for security debugging
     488           0 :         puts ("CURVE I: invalid handshake from client (public key)");
     489           0 :         errno = EPROTO;
     490           0 :         return -1;
     491             :     }
     492             : 
     493             :     //  Precompute connection secret from client key
     494           9 :     rc = crypto_box_beforenm (cn_precom, cn_client, cn_secret);
     495           9 :     zmq_assert (rc == 0);
     496             : 
     497             :     //  Use ZAP protocol (RFC 27) to authenticate the user.
     498           9 :     rc = session->zap_connect ();
     499           9 :     if (rc == 0) {
     500           6 :         send_zap_request (client_key);
     501           6 :         rc = receive_and_process_zap_reply ();
     502           6 :         if (rc == 0)
     503           0 :             state = status_code == "200"
     504             :                 ? send_ready
     505           0 :                 : send_error;
     506             :         else
     507           6 :         if (errno == EAGAIN)
     508           6 :             state = expect_zap_reply;
     509             :         else
     510             :             return -1;
     511             :     }
     512             :     else
     513           3 :         state = send_ready;
     514             : 
     515             :     return parse_metadata (initiate_plaintext + crypto_box_ZEROBYTES + 128,
     516           9 :                            clen - crypto_box_ZEROBYTES - 128);
     517             : }
     518             : 
     519           6 : int zmq::curve_server_t::produce_ready (msg_t *msg_)
     520             : {
     521             :     uint8_t ready_nonce [crypto_box_NONCEBYTES];
     522             :     uint8_t ready_plaintext [crypto_box_ZEROBYTES + 256];
     523             :     uint8_t ready_box [crypto_box_BOXZEROBYTES + 16 + 256];
     524             : 
     525             :     //  Create Box [metadata](S'->C')
     526             :     memset (ready_plaintext, 0, crypto_box_ZEROBYTES);
     527           6 :     uint8_t *ptr = ready_plaintext + crypto_box_ZEROBYTES;
     528             : 
     529             :     //  Add socket type property
     530           6 :     const char *socket_type = socket_type_string (options.type);
     531           6 :     ptr += add_property (ptr, "Socket-Type", socket_type, strlen (socket_type));
     532             : 
     533             :     //  Add identity property
     534           6 :     if (options.type == ZMQ_REQ
     535           6 :     ||  options.type == ZMQ_DEALER
     536           6 :     ||  options.type == ZMQ_ROUTER)
     537           6 :         ptr += add_property (ptr, "Identity", options.identity, options.identity_size);
     538             : 
     539           6 :     const size_t mlen = ptr - ready_plaintext;
     540             : 
     541             :     memcpy (ready_nonce, "CurveZMQREADY---", 16);
     542           6 :     put_uint64 (ready_nonce + 16, cn_nonce);
     543             : 
     544             :     int rc = crypto_box_afternm (ready_box, ready_plaintext,
     545           6 :                                  mlen, ready_nonce, cn_precom);
     546           6 :     zmq_assert (rc == 0);
     547             : 
     548           6 :     rc = msg_->init_size (14 + mlen - crypto_box_BOXZEROBYTES);
     549           6 :     errno_assert (rc == 0);
     550             : 
     551           6 :     uint8_t *ready = static_cast <uint8_t *> (msg_->data ());
     552             : 
     553             :     memcpy (ready, "\x05READY", 6);
     554             :     //  Short nonce, prefixed by "CurveZMQREADY---"
     555           6 :     memcpy (ready + 6, ready_nonce + 16, 8);
     556             :     //  Box [metadata](S'->C')
     557           6 :     memcpy (ready + 14, ready_box + crypto_box_BOXZEROBYTES,
     558           6 :             mlen - crypto_box_BOXZEROBYTES);
     559             : 
     560           6 :     cn_nonce++;
     561             : 
     562           6 :     return 0;
     563             : }
     564             : 
     565           3 : int zmq::curve_server_t::produce_error (msg_t *msg_) const
     566             : {
     567           6 :     zmq_assert (status_code.length () == 3);
     568           6 :     const int rc = msg_->init_size (6 + 1 + status_code.length ());
     569           3 :     zmq_assert (rc == 0);
     570           3 :     char *msg_data = static_cast <char *> (msg_->data ());
     571             :     memcpy (msg_data, "\5ERROR", 6);
     572           3 :     msg_data [6] = sizeof status_code;
     573           6 :     memcpy (msg_data + 7, status_code.c_str (), status_code.length ());
     574           3 :     return 0;
     575             : }
     576             : 
     577           6 : void zmq::curve_server_t::send_zap_request (const uint8_t *key)
     578             : {
     579             :     int rc;
     580             :     msg_t msg;
     581             : 
     582             :     //  Address delimiter frame
     583           6 :     rc = msg.init ();
     584           6 :     errno_assert (rc == 0);
     585           6 :     msg.set_flags (msg_t::more);
     586           6 :     rc = session->write_zap_msg (&msg);
     587           6 :     errno_assert (rc == 0);
     588             : 
     589             :     //  Version frame
     590           6 :     rc = msg.init_size (3);
     591           6 :     errno_assert (rc == 0);
     592           6 :     memcpy (msg.data (), "1.0", 3);
     593           6 :     msg.set_flags (msg_t::more);
     594           6 :     rc = session->write_zap_msg (&msg);
     595           6 :     errno_assert (rc == 0);
     596             : 
     597             :     //  Request ID frame
     598           6 :     rc = msg.init_size (1);
     599           6 :     errno_assert (rc == 0);
     600           6 :     memcpy (msg.data (), "1", 1);
     601           6 :     msg.set_flags (msg_t::more);
     602           6 :     rc = session->write_zap_msg (&msg);
     603           6 :     errno_assert (rc == 0);
     604             : 
     605             :     //  Domain frame
     606          12 :     rc = msg.init_size (options.zap_domain.length ());
     607           6 :     errno_assert (rc == 0);
     608          12 :     memcpy (msg.data (), options.zap_domain.c_str (), options.zap_domain.length ());
     609           6 :     msg.set_flags (msg_t::more);
     610           6 :     rc = session->write_zap_msg (&msg);
     611           6 :     errno_assert (rc == 0);
     612             : 
     613             :     //  Address frame
     614          12 :     rc = msg.init_size (peer_address.length ());
     615           6 :     errno_assert (rc == 0);
     616          12 :     memcpy (msg.data (), peer_address.c_str (), peer_address.length ());
     617           6 :     msg.set_flags (msg_t::more);
     618           6 :     rc = session->write_zap_msg (&msg);
     619           6 :     errno_assert (rc == 0);
     620             : 
     621             :     //  Identity frame
     622           6 :     rc = msg.init_size (options.identity_size);
     623           6 :     errno_assert (rc == 0);
     624           6 :     memcpy (msg.data (), options.identity, options.identity_size);
     625           6 :     msg.set_flags (msg_t::more);
     626           6 :     rc = session->write_zap_msg (&msg);
     627           6 :     errno_assert (rc == 0);
     628             : 
     629             :     //  Mechanism frame
     630           6 :     rc = msg.init_size (5);
     631           6 :     errno_assert (rc == 0);
     632           6 :     memcpy (msg.data (), "CURVE", 5);
     633           6 :     msg.set_flags (msg_t::more);
     634           6 :     rc = session->write_zap_msg (&msg);
     635           6 :     errno_assert (rc == 0);
     636             : 
     637             :     //  Credentials frame
     638           6 :     rc = msg.init_size (crypto_box_PUBLICKEYBYTES);
     639           6 :     errno_assert (rc == 0);
     640           6 :     memcpy (msg.data (), key, crypto_box_PUBLICKEYBYTES);
     641           6 :     rc = session->write_zap_msg (&msg);
     642           6 :     errno_assert (rc == 0);
     643           6 : }
     644             : 
     645          12 : int zmq::curve_server_t::receive_and_process_zap_reply ()
     646             : {
     647          12 :     int rc = 0;
     648             :     msg_t msg [7];  //  ZAP reply consists of 7 frames
     649             : 
     650             :     //  Initialize all reply frames
     651          96 :     for (int i = 0; i < 7; i++) {
     652          84 :         rc = msg [i].init ();
     653          84 :         errno_assert (rc == 0);
     654             :     }
     655             : 
     656          42 :     for (int i = 0; i < 7; i++) {
     657          48 :         rc = session->read_zap_msg (&msg [i]);
     658          48 :         if (rc == -1)
     659             :             break;
     660          42 :         if ((msg [i].flags () & msg_t::more) == (i < 6? 0: msg_t::more)) {
     661             :             //  Temporary support for security debugging
     662           0 :             puts ("CURVE I: ZAP handler sent incomplete reply message");
     663           0 :             errno = EPROTO;
     664           0 :             rc = -1;
     665           0 :             break;
     666             :         }
     667             :     }
     668             : 
     669          12 :     if (rc != 0)
     670             :         goto error;
     671             : 
     672             :     //  Address delimiter frame
     673           6 :     if (msg [0].size () > 0) {
     674             :         //  Temporary support for security debugging
     675           0 :         puts ("CURVE I: ZAP handler sent malformed reply message");
     676           0 :         errno = EPROTO;
     677           0 :         rc = -1;
     678           0 :         goto error;
     679             :     }
     680             : 
     681             :     //  Version frame
     682           6 :     if (msg [1].size () != 3 || memcmp (msg [1].data (), "1.0", 3)) {
     683             :         //  Temporary support for security debugging
     684           0 :         puts ("CURVE I: ZAP handler sent bad version number");
     685           0 :         errno = EPROTO;
     686           0 :         rc = -1;
     687           0 :         goto error;
     688             :     }
     689             : 
     690             :     //  Request id frame
     691           6 :     if (msg [2].size () != 1 || memcmp (msg [2].data (), "1", 1)) {
     692             :         //  Temporary support for security debugging
     693           0 :         puts ("CURVE I: ZAP handler sent bad request ID");
     694           0 :         errno = EPROTO;
     695           0 :         rc = -1;
     696           0 :         goto error;
     697             :     }
     698             : 
     699             :     //  Status code frame
     700           6 :     if (msg [3].size () != 3) {
     701             :         //  Temporary support for security debugging
     702           0 :         puts ("CURVE I: ZAP handler rejected client authentication");
     703           0 :         errno = EACCES;
     704           0 :         rc = -1;
     705           0 :         goto error;
     706             :     }
     707             : 
     708             :     //  Save status code
     709           6 :     status_code.assign (static_cast <char *> (msg [3].data ()), 3);
     710             : 
     711             :     //  Save user id
     712           6 :     set_user_id (msg [5].data (), msg [5].size ());
     713             : 
     714             :     //  Process metadata frame
     715           6 :     rc = parse_metadata (static_cast <const unsigned char*> (msg [6].data ()),
     716          12 :                          msg [6].size (), true);
     717             : 
     718             : error:
     719          96 :     for (int i = 0; i < 7; i++) {
     720          84 :         const int rc2 = msg [i].close ();
     721          84 :         errno_assert (rc2 == 0);
     722             :     }
     723             : 
     724          12 :     return rc;
     725             : }
     726             : 
     727             : #endif

Generated by: LCOV version 1.10