From 04db842dcc10c7790fd77d0f8a44aa41709dee59 Mon Sep 17 00:00:00 2001 From: Chris Busbey Date: Thu, 7 Nov 2013 11:49:45 -0800 Subject: [PATCH] added ready for meta data exchange at end of gss handshake --- src/gssapi_client.cpp | 31 ++++++++++++++++------ src/gssapi_client.hpp | 7 +++-- src/gssapi_mechanism_base.cpp | 49 ++++++++++++++++++++++++++++++++++- src/gssapi_mechanism_base.hpp | 15 ++++++++--- src/gssapi_server.cpp | 30 ++++++++++++++++----- src/gssapi_server.hpp | 7 +++-- 6 files changed, 113 insertions(+), 26 deletions(-) diff --git a/src/gssapi_client.cpp b/src/gssapi_client.cpp index f2e7a1f1..bafe34b0 100644 --- a/src/gssapi_client.cpp +++ b/src/gssapi_client.cpp @@ -32,8 +32,7 @@ #include "wire.hpp" zmq::gssapi_client_t::gssapi_client_t (const options_t &options_) : - gssapi_mechanism_base_t (), - mechanism_t (options_), + gssapi_mechanism_base_t (options_), state (call_next_init), token_ptr (GSS_C_NO_BUFFER), mechs (), @@ -55,6 +54,14 @@ zmq::gssapi_client_t::~gssapi_client_t () int zmq::gssapi_client_t::next_handshake_command (msg_t *msg_) { + if (state == send_ready) { + int rc = produce_ready(msg_); + if (rc == 0) + state = connected; + + return rc; + } + if (security_context_established) { state = connected; return 0; @@ -74,8 +81,10 @@ int zmq::gssapi_client_t::next_handshake_command (msg_t *msg_) if (maj_stat != GSS_S_CONTINUE_NEEDED && maj_stat != GSS_S_COMPLETE) return -1; - if (maj_stat == GSS_S_COMPLETE) + if (maj_stat == GSS_S_COMPLETE) { security_context_established = true; + state = recv_ready; + } else state = recv_next_token; @@ -84,6 +93,14 @@ int zmq::gssapi_client_t::next_handshake_command (msg_t *msg_) int zmq::gssapi_client_t::process_handshake_command (msg_t *msg_) { + if (state == recv_ready) { + int rc = process_ready(msg_); + if (rc == 0) + state = send_ready; + + return rc; + } + if (state != recv_next_token) { errno = EPROTO; return -1; @@ -92,13 +109,11 @@ int zmq::gssapi_client_t::process_handshake_command (msg_t *msg_) if (process_next_token (msg_) < 0) return -1; - if (maj_stat == GSS_S_COMPLETE) - security_context_established = true; - else if (maj_stat == GSS_S_CONTINUE_NEEDED) - state = call_next_init; - else + if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED) return -1; + state = call_next_init; + errno_assert (msg_->close () == 0); errno_assert (msg_->init () == 0); diff --git a/src/gssapi_client.hpp b/src/gssapi_client.hpp index 6c28a8d1..d08c7afd 100644 --- a/src/gssapi_client.hpp +++ b/src/gssapi_client.hpp @@ -21,8 +21,6 @@ #define __ZMQ_GSSAPI_CLIENT_HPP_INCLUDED__ #include "gssapi_mechanism_base.hpp" -#include "mechanism.hpp" -#include "options.hpp" namespace zmq { @@ -30,8 +28,7 @@ namespace zmq class msg_t; class gssapi_client_t : - public gssapi_mechanism_base_t, - public mechanism_t + public gssapi_mechanism_base_t { public: @@ -51,6 +48,8 @@ namespace zmq call_next_init, send_next_token, recv_next_token, + send_ready, + recv_ready, connected }; diff --git a/src/gssapi_mechanism_base.cpp b/src/gssapi_mechanism_base.cpp index 653442c4..136ef53d 100644 --- a/src/gssapi_mechanism_base.cpp +++ b/src/gssapi_mechanism_base.cpp @@ -31,7 +31,8 @@ #include "gssapi_mechanism_base.hpp" #include "wire.hpp" -zmq::gssapi_mechanism_base_t::gssapi_mechanism_base_t () : +zmq::gssapi_mechanism_base_t::gssapi_mechanism_base_t (const options_t & options_) : + mechanism_t(options_), send_tok (), recv_tok (), /// FIXME remove? in_buf (), @@ -235,6 +236,52 @@ int zmq::gssapi_mechanism_base_t::process_initiate (msg_t *msg_, void **token_va return 0; } +int zmq::gssapi_mechanism_base_t::produce_ready (msg_t *msg_) const +{ + unsigned char * const command_buffer = (unsigned char *) malloc (512); + alloc_assert (command_buffer); + + unsigned char *ptr = command_buffer; + + // Add command name + memcpy (ptr, "\x05READY", 6); + ptr += 6; + + // 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 + || options.type == ZMQ_ROUTER) { + ptr += add_property (ptr, "Identity", + options.identity, options.identity_size); + } + + 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; +} + +int zmq::gssapi_mechanism_base_t::process_ready (msg_t *msg_) +{ + const unsigned char *ptr = static_cast (msg_->data ()); + size_t bytes_left = msg_->size (); + + if (bytes_left < 6 || memcmp (ptr, "\x05READY", 6)) { + errno = EPROTO; + return -1; + } + ptr += 6; + bytes_left -= 6; + return parse_metadata (ptr, bytes_left); +} + int zmq::gssapi_mechanism_base_t::acquire_credentials (char * service_name_, gss_cred_id_t * cred_) { OM_uint32 maj_stat; diff --git a/src/gssapi_mechanism_base.hpp b/src/gssapi_mechanism_base.hpp index 3bdb1a1b..d84bdc85 100644 --- a/src/gssapi_mechanism_base.hpp +++ b/src/gssapi_mechanism_base.hpp @@ -22,7 +22,9 @@ #include #include -#include + +#include "mechanism.hpp" +#include "options.hpp" namespace zmq { @@ -33,10 +35,11 @@ namespace zmq /// For example, clients and servers both need to produce and /// process context-level GSSAPI tokens (via INITIATE commands) /// and per-message GSSAPI tokens (via MESSAGE commands). - class gssapi_mechanism_base_t + class gssapi_mechanism_base_t: + public mechanism_t { public: - gssapi_mechanism_base_t (); + gssapi_mechanism_base_t (const options_t &options_); virtual ~gssapi_mechanism_base_t () = 0; protected: @@ -47,6 +50,12 @@ namespace zmq // Process a context-level GSSAPI token (INITIATE command) // during security context initialization. int process_initiate (msg_t *msg_, void **data_, size_t &data_len_); + + // Produce a metadata ready msg (READY) to conclude handshake + int produce_ready (msg_t *msg_) const; + + // Process a metadata ready msg (READY) + int process_ready (msg_t *msg_); // Encode a per-message GSSAPI token (MESSAGE command) using // the established security context. diff --git a/src/gssapi_server.cpp b/src/gssapi_server.cpp index c4dc667c..5cb3cef0 100644 --- a/src/gssapi_server.cpp +++ b/src/gssapi_server.cpp @@ -34,8 +34,7 @@ zmq::gssapi_server_t::gssapi_server_t (session_base_t *session_, const std::string &peer_address_, const options_t &options_) : - gssapi_mechanism_base_t (), - mechanism_t (options_), + gssapi_mechanism_base_t (options_), session (session_), peer_address (peer_address_), state (recv_next_token), @@ -57,6 +56,14 @@ zmq::gssapi_server_t::~gssapi_server_t () int zmq::gssapi_server_t::next_handshake_command (msg_t *msg_) { + if (state == send_ready) { + int rc = produce_ready(msg_); + if (rc == 0) + state = recv_ready; + + return rc; + } + if (state != send_next_token) { errno = EAGAIN; return -1; @@ -71,22 +78,33 @@ int zmq::gssapi_server_t::next_handshake_command (msg_t *msg_) if (maj_stat == GSS_S_COMPLETE) { gss_release_name(&min_stat, &target_name); security_context_established = true; - state = connected; - } - else { - state = recv_next_token; } + state = recv_next_token; + return 0; } int zmq::gssapi_server_t::process_handshake_command (msg_t *msg_) { + if (state == recv_ready) { + int rc = process_ready(msg_); + if (rc == 0) + state = connected; + + return rc; + } + if (state != recv_next_token) { errno = EPROTO; return -1; } + if (security_context_established) { + state = send_ready; + return 0; + } + if (process_next_token (msg_) < 0) return -1; diff --git a/src/gssapi_server.hpp b/src/gssapi_server.hpp index 91cb9d34..146a4a2e 100644 --- a/src/gssapi_server.hpp +++ b/src/gssapi_server.hpp @@ -21,8 +21,6 @@ #define __ZMQ_GSSAPI_SERVER_HPP_INCLUDED__ #include "gssapi_mechanism_base.hpp" -#include "mechanism.hpp" -#include "options.hpp" namespace zmq { @@ -31,8 +29,7 @@ namespace zmq class session_base_t; class gssapi_server_t : - public gssapi_mechanism_base_t, - public mechanism_t + public gssapi_mechanism_base_t { public: @@ -54,6 +51,8 @@ namespace zmq enum state_t { send_next_token, recv_next_token, + send_ready, + recv_ready, connected };