diff --git a/src/gssapi_client.cpp b/src/gssapi_client.cpp index 5ef45ffe..14ad21e2 100644 --- a/src/gssapi_client.cpp +++ b/src/gssapi_client.cpp @@ -102,6 +102,20 @@ int zmq::gssapi_client_t::process_handshake_command (msg_t *msg_) return rc; } +int zmq::gssapi_client_t::encode (msg_t *msg_) +{ + int rc = 0; + zmq_assert (state == ready); + return rc; +} + +int zmq::gssapi_client_t::decode (msg_t *msg_) +{ + int rc = 0; + zmq_assert (state == ready); + return rc; +} + bool zmq::gssapi_client_t::is_handshake_complete () const { fprintf(stderr, "%s:%d: is_handshake_complete=%d, security_context_established=%d\n", __FILE__, __LINE__, (state==ready), security_context_established); /// FIXME remove diff --git a/src/gssapi_client.hpp b/src/gssapi_client.hpp index 5613ce59..4cefa1e2 100644 --- a/src/gssapi_client.hpp +++ b/src/gssapi_client.hpp @@ -41,6 +41,8 @@ namespace zmq // mechanism implementation virtual int next_handshake_command (msg_t *msg_); virtual int process_handshake_command (msg_t *msg_); + virtual int encode (msg_t *msg_); + virtual int decode (msg_t *msg_); virtual bool is_handshake_complete () const; private: diff --git a/src/gssapi_mechanism_base.cpp b/src/gssapi_mechanism_base.cpp index 3d8ed71e..ea52db4b 100644 --- a/src/gssapi_mechanism_base.cpp +++ b/src/gssapi_mechanism_base.cpp @@ -124,7 +124,7 @@ int zmq::gssapi_mechanism_base_t::process_token (msg_t *msg_, int &flags_, void ptr += 4; bytes_left -= 4; - // Get token value + // Get token value. TODO do unwrap here to prevent this extra memcpy. if (bytes_left < token_length_) { errno = EPROTO; return -1; @@ -145,6 +145,72 @@ int zmq::gssapi_mechanism_base_t::process_token (msg_t *msg_, int &flags_, void return 0; } +/// TODO add support for TOKEN_SEND_MIC +/// TODO use gss_wrap_size_limit +int +zmq::gssapi_mechanism_base_t::produce_message (msg_t *msg_) +{ + // wrap it + int state; + gss_buffer_desc plaintext; + gss_buffer_desc wrapped; + plaintext.value = msg_->data (); + plaintext.length = msg_->size (); + + maj_stat = gss_wrap(&min_stat, context, 1, GSS_C_QOP_DEFAULT, + &plaintext, &state, &wrapped); + + zmq_assert (maj_stat == GSS_S_COMPLETE); + zmq_assert (state); + + // prepare msg_ for wrapped text + int rc = msg_->close (); + zmq_assert (rc == 0); + + // produce token + const int flags = (TOKEN_DATA | TOKEN_WRAPPED | TOKEN_ENCRYPTED); + rc = produce_token (msg_, flags, wrapped.value, wrapped.length); + zmq_assert (rc == 0); + gss_release_buffer (&min_stat, &wrapped); + + return 0; +} + +int +zmq::gssapi_mechanism_base_t::process_message (msg_t *msg_) +{ + // process token + int flags; + gss_buffer_desc wrapped; + int rc = process_token(msg_, flags, &wrapped.value, wrapped.length); + zmq_assert (rc == 0); + + // ensure valid security context + zmq_assert (context != GSS_C_NO_CONTEXT); + zmq_assert (flags & TOKEN_WRAPPED); + zmq_assert (flags & TOKEN_ENCRYPTED); + + // unwrap + int state; + gss_buffer_desc plaintext; + maj_stat = gss_unwrap(&min_stat, context, &wrapped, &plaintext, + &state, (gss_qop_t *) NULL); + + zmq_assert(maj_stat == GSS_S_COMPLETE); + zmq_assert(state); + + // re-init msg_ with plaintext + rc = msg_->close (); + zmq_assert (rc == 0); + msg_->init_size (plaintext.length); + zmq_assert (rc == 0); + + memcpy (msg_->data (), plaintext.value, plaintext.length); + gss_release_buffer (&min_stat, &plaintext); + gss_release_buffer (&min_stat, &wrapped); + return 0; +} + 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 8beafda9..848411ae 100644 --- a/src/gssapi_mechanism_base.hpp +++ b/src/gssapi_mechanism_base.hpp @@ -29,9 +29,8 @@ namespace zmq class msg_t; - // Both gssapi_server and gssapi_client need to produce and process - // GSSAPI tokens. Common implementation is captured here. - + /// Both gssapi_server and gssapi_client need to produce and process + /// GSSAPI tokens. Common implementation is captured here. class gssapi_mechanism_base_t { public: @@ -39,8 +38,15 @@ namespace zmq virtual ~gssapi_mechanism_base_t () = 0; protected: + /// Produce a security context initialization token int produce_token (msg_t *msg_, int flags_, void *token_value_, size_t token_length_); + /// Process a security context initialization token int process_token (msg_t *msg_, int &flags_, void **token_value_, size_t &token_length_); + /// Produce a wrapped message using the established security context + int produce_message (msg_t *msg_); + /// Process a wrapped message using the established security context + int process_message (msg_t *msg_); + /// Acquire security context credentials static int acquire_credentials (char * service_name_, gss_cred_id_t * cred_); protected: diff --git a/src/gssapi_server.cpp b/src/gssapi_server.cpp index c09b898c..a4d8337b 100644 --- a/src/gssapi_server.cpp +++ b/src/gssapi_server.cpp @@ -107,6 +107,20 @@ int zmq::gssapi_server_t::process_handshake_command (msg_t *msg_) return rc; } +int zmq::gssapi_server_t::encode (msg_t *msg_) +{ + int rc = 0; + zmq_assert (state == ready); + return rc; +} + +int zmq::gssapi_server_t::decode (msg_t *msg_) +{ + int rc = 0; + zmq_assert (state == ready); + return rc; +} + int zmq::gssapi_server_t::zap_msg_available () { return 0; diff --git a/src/gssapi_server.hpp b/src/gssapi_server.hpp index 492c77ec..62ef0f2a 100644 --- a/src/gssapi_server.hpp +++ b/src/gssapi_server.hpp @@ -44,6 +44,8 @@ namespace zmq // mechanism implementation virtual int next_handshake_command (msg_t *msg_); virtual int process_handshake_command (msg_t *msg_); + virtual int encode (msg_t *msg_); + virtual int decode (msg_t *msg_); virtual int zap_msg_available (); virtual bool is_handshake_complete () const;