From 43f4c286605651dd15d6049e1986c141acb9e69d Mon Sep 17 00:00:00 2001 From: Jim Garlick Date: Fri, 14 Apr 2017 15:11:14 -0700 Subject: [PATCH 1/5] gssapi: define HAVE_LIBGSSAPI_KRB5 in configure.ac Problem: configure.ac is not setting HAVE_LIBGSSAPI_KRB5 in src/platform.hpp when --with-libgssapi_krb5 is specified Commit 09e868b74379f9c4b0e3a487b246a41d44606d96 switched the libgssapi_krb5 check from AC_CHECK_LIB to AC_SEARCH_LIBS, but neglected to add an AC_DEFINE for HAVE_LIBGSSAPI_KRB5, thus the GSSAPI code is never compiled. Solution: Add missing AC_DEFINE of HAVE_LIBGSSAPI_KRB5. --- configure.ac | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index bbf854cc..320f0225 100644 --- a/configure.ac +++ b/configure.ac @@ -427,7 +427,8 @@ AC_ARG_WITH([libgssapi_krb5], [AS_HELP_STRING([--with-libgssapi_krb5], # conditionally require libgssapi_krb5 if test "x$require_libgssapi_krb5_ext" != "xno"; then AC_CHECK_HEADERS(gssapi/gssapi_generic.h) - AC_SEARCH_LIBS([gss_init_sec_context], [gssapi_krb5 gssapi],, + AC_SEARCH_LIBS([gss_init_sec_context], [gssapi_krb5 gssapi], + AC_DEFINE(HAVE_LIBGSSAPI_KRB5, [1], [Enabled GSSAPI security]), AC_MSG_ERROR(libgssapi_krb5 is needed for GSSAPI security)) fi From c371824b5b120f1bdaa183fcc733abc75a727067 Mon Sep 17 00:00:00 2001 From: Jim Garlick Date: Tue, 18 Apr 2017 11:37:40 -0700 Subject: [PATCH 2/5] gssapi: document ZMQ_GSSAPI_PRINCIPAL as optional Problem: the ZMQ_GSSAPI_PRINCIPAL socket option is described as mandatory in the zmq_gssapi(7) manual page. In fact it is optional. Solution: Describe ZMQ_GSSAPI_PRINCIPAL as optional. If unspecified, default credentials are used. --- doc/zmq_gssapi.txt | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/doc/zmq_gssapi.txt b/doc/zmq_gssapi.txt index 3b32ec84..b98a4816 100644 --- a/doc/zmq_gssapi.txt +++ b/doc/zmq_gssapi.txt @@ -22,16 +22,17 @@ CLIENT AND SERVER ROLES ----------------------- A socket using GSSAPI can be either client or server, but not both. -To become either a GSSAPI client or server, the application sets the -ZMQ_GSSAPI_PRINCIPAL option to provide the socket with the name of the principal -for whom GSSAPI credentials should be acquired. +To become a GSSAPI server, the application sets the ZMQ_GSSAPI_SERVER +option on the socket. -To become a GSSAPI server, the application additionally sets the -ZMQ_GSSAPI_SERVER option on the socket. +To become a GSSAPI client, the application sets the ZMQ_GSSAPI_SERVICE_PRINCIPAL +option to the name of the principal on the server to which it intends to +connect. -To become a GSSAPI client, the application additionally sets the -ZMQ_GSSAPI_SERVICE_PRINCIPAL option to the name of the principal of the server -to which it intends to connect. +On client or server, the application may additionally set the +ZMQ_GSSAPI_PRINCIPAL option to provide the socket with the name of the +principal for whom GSSAPI credentials should be acquired. If this option +is not set, default credentials are used. OPTIONAL ENCRYPTION From f2b579ce027f4acf4001033ed5a4471fdd77ebb6 Mon Sep 17 00:00:00 2001 From: Jim Garlick Date: Tue, 18 Apr 2017 16:06:53 -0700 Subject: [PATCH 3/5] gssapi: use GSS_C_BOTH to acquire credentials Problem: if client sets the ZMQ_GSSAPI_PRINCIPAL to a valid principal, authentication fails. When an application sets ZMQ_GSSAPI_PRINCIPAL, whether as a client or a server, libzmq internally calls gss_acquire_cred() with cred_usage=GSS_C_ACCEPT. This cred_usage setting is for acceptors (servers) only, thus it doesn't work for initiators (clients). Solution: Change the cred_usage parameter to GSS_C_BOTH to allow initiators to set ZMQ_GSSAPI_PRINCIPAL. --- src/gssapi_mechanism_base.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gssapi_mechanism_base.cpp b/src/gssapi_mechanism_base.cpp index f00591bd..77301882 100644 --- a/src/gssapi_mechanism_base.cpp +++ b/src/gssapi_mechanism_base.cpp @@ -338,7 +338,7 @@ int zmq::gssapi_mechanism_base_t::acquire_credentials (char * service_name_, gss return -1; maj_stat = gss_acquire_cred (&min_stat, server_name, 0, - GSS_C_NO_OID_SET, GSS_C_ACCEPT, + GSS_C_NO_OID_SET, GSS_C_BOTH, cred_, NULL, NULL); if (maj_stat != GSS_S_COMPLETE) From 4e22dd0e9709587c4b211066212510c37276ff8c Mon Sep 17 00:00:00 2001 From: Jim Garlick Date: Wed, 19 Apr 2017 16:04:41 -0700 Subject: [PATCH 4/5] gssapi: fail if client sets wrong principal Problem: if client sets ZMQ_GSSAPI_PRINCIPAL to a name for which credentials cannot be obtained, authentication proceeds with default credentials. Solution: Before initializing the security context, check whether there was a failed attempt to acquire credentials for a specific principal and bail out if so. Fixes #2531 --- src/gssapi_client.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gssapi_client.cpp b/src/gssapi_client.cpp index 9eb598ab..6d7444cf 100644 --- a/src/gssapi_client.cpp +++ b/src/gssapi_client.cpp @@ -166,6 +166,10 @@ zmq::mechanism_t::status_t zmq::gssapi_client_t::status () const int zmq::gssapi_client_t::initialize_context () { + // principal was specified but credentials could not be acquired + if (principal_name != NULL && cred == NULL) + return -1; + // First time through, import service_name into target_name if (target_name == GSS_C_NO_NAME) { send_tok.value = service_name; From 2b9a352a3c850dac8636dacc4aa3a51e97bac272 Mon Sep 17 00:00:00 2001 From: Jim Garlick Date: Wed, 19 Apr 2017 17:08:14 -0700 Subject: [PATCH 5/5] gssapi: use gss_buffer_desc consistently Problem: one call to gss_import_name() includes the terminating NULL in a gss_buffer_desc.length, and one doesn't. According to the examples at: http://docs.oracle.com/cd/E19253-01/816-4863/overview-22/index.html the NULL should be included in the length. Solution: Fix one case to include the terminating NULL in the length. --- src/gssapi_client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gssapi_client.cpp b/src/gssapi_client.cpp index 6d7444cf..495f4ab0 100644 --- a/src/gssapi_client.cpp +++ b/src/gssapi_client.cpp @@ -173,7 +173,7 @@ int zmq::gssapi_client_t::initialize_context () // First time through, import service_name into target_name if (target_name == GSS_C_NO_NAME) { send_tok.value = service_name; - send_tok.length = strlen(service_name); + send_tok.length = strlen(service_name) + 1; OM_uint32 maj = gss_import_name(&min_stat, &send_tok, GSS_C_NT_HOSTBASED_SERVICE, &target_name);