gssapi: add NAMETYPE socket options

Problem: principals are looked up unconditionally
with the GSS_C_NT_HOSTBASED_SERVICE name type.

Solution: Add two new socket options to set the name type
for ZMQ_GSSAPI_PRINCIPAL and ZMQ_GSSAPI_SERVICE_PRINCIPAL:

ZMQ_GSSAPI_PRINCIPAL_NAMETYPE
ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE

They take an integer argument which must be one of
ZMQ_GSSAPI_NT_HOSTBASED (0) - default
ZMQ_GSSAPI_NT_USER_NAME (1)
ZMQ_GSSAPI_NT_KRB5_PRINCIPAL (2)

These correspond to GSSAPI name types of:
GSS_C_NT_HOSTBASED_SERVICE
GSS_C_NT_USER_NAME
GSS_KRB5_NT_PRINCIPAL_NAME

Fixes #2542
This commit is contained in:
Jim Garlick 2017-04-20 16:28:30 -07:00
parent 4783605b78
commit 0b185e8297
8 changed files with 62 additions and 6 deletions

View File

@ -368,6 +368,13 @@ ZMQ_EXPORT const char *zmq_msg_gets (const zmq_msg_t *msg, const char *property)
#define ZMQ_VMCI_BUFFER_MAX_SIZE 87
#define ZMQ_VMCI_CONNECT_TIMEOUT 88
#define ZMQ_USE_FD 89
#define ZMQ_GSSAPI_PRINCIPAL_NAMETYPE 90
#define ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE 91
/* GSSAPI principal name types */
#define ZMQ_GSSAPI_NT_HOSTBASED 0
#define ZMQ_GSSAPI_NT_USER_NAME 1
#define ZMQ_GSSAPI_NT_KRB5_PRINCIPAL 2
/* Message options */
#define ZMQ_MORE 1

View File

@ -51,6 +51,7 @@ zmq::gssapi_client_t::gssapi_client_t (const options_t &options_) :
service_name = static_cast <char *>(malloc(service_size+1));
assert(service_name);
memcpy(service_name, options_.gss_service_principal.c_str(), service_size+1 );
service_name_type = convert_nametype (options_.gss_service_principal_nt);
maj_stat = GSS_S_COMPLETE;
if(!options_.gss_principal.empty())
@ -60,7 +61,8 @@ zmq::gssapi_client_t::gssapi_client_t (const options_t &options_) :
assert(principal_name);
memcpy(principal_name, options_.gss_principal.c_str(), principal_size+1 );
if (acquire_credentials (principal_name, &cred) != 0)
if (acquire_credentials (principal_name, &cred,
options_.gss_principal_nt) != 0)
maj_stat = GSS_S_FAILURE;
}
@ -175,7 +177,7 @@ int zmq::gssapi_client_t::initialize_context ()
send_tok.value = service_name;
send_tok.length = strlen(service_name) + 1;
OM_uint32 maj = gss_import_name(&min_stat, &send_tok,
GSS_C_NT_HOSTBASED_SERVICE,
service_name_type,
&target_name);
if (maj != GSS_S_COMPLETE)

View File

@ -68,6 +68,8 @@ namespace zmq
// Human-readable principal name of the service we are connecting to
char * service_name;
gss_OID service_name_type;
// Current FSM state
state_t state;

View File

@ -321,18 +321,36 @@ int zmq::gssapi_mechanism_base_t::process_ready (msg_t *msg_)
return parse_metadata (ptr, bytes_left);
}
int zmq::gssapi_mechanism_base_t::acquire_credentials (char * service_name_, gss_cred_id_t * cred_)
const gss_OID zmq::gssapi_mechanism_base_t::convert_nametype (int zmq_nametype)
{
switch (zmq_nametype) {
case ZMQ_GSSAPI_NT_HOSTBASED:
return GSS_C_NT_HOSTBASED_SERVICE;
case ZMQ_GSSAPI_NT_USER_NAME:
return GSS_C_NT_USER_NAME;
case ZMQ_GSSAPI_NT_KRB5_PRINCIPAL:
#ifdef GSS_KRB5_NT_PRINCIPAL_NAME
return (gss_OID)GSS_KRB5_NT_PRINCIPAL_NAME;
#else
return GSS_C_NT_USER_NAME;
#endif
}
return NULL;
}
int zmq::gssapi_mechanism_base_t::acquire_credentials (char * service_name_, gss_cred_id_t * cred_, int zmq_name_type_)
{
OM_uint32 maj_stat;
OM_uint32 min_stat;
gss_name_t server_name;
gss_OID name_type = convert_nametype (zmq_name_type_);
gss_buffer_desc name_buf;
name_buf.value = service_name_;
name_buf.length = strlen ((char *) name_buf.value) + 1;
maj_stat = gss_import_name (&min_stat, &name_buf,
GSS_C_NT_HOSTBASED_SERVICE, &server_name);
name_type, &server_name);
if (maj_stat != GSS_S_COMPLETE)
return -1;

View File

@ -79,10 +79,14 @@ namespace zmq
// the established security context.
int decode_message (msg_t *msg_);
// Convert ZMQ_GSSAPI_NT values to GSSAPI name_type
static const gss_OID convert_nametype (int zmq_name_type_);
// Acquire security context credentials from the
// underlying mechanism.
static int acquire_credentials (char * principal_name_,
gss_cred_id_t * cred_);
gss_cred_id_t * cred_,
int zmq_name_type_);
protected:
// Opaque GSSAPI token for outgoing data

View File

@ -59,7 +59,8 @@ zmq::gssapi_server_t::gssapi_server_t (session_base_t *session_,
assert(principal_name);
memcpy(principal_name, options_.gss_principal.c_str(), principal_size+1 );
if (acquire_credentials (principal_name, &cred) != 0)
if (acquire_credentials (principal_name, &cred,
options_.gss_principal_nt) != 0)
maj_stat = GSS_S_FAILURE;
}
}

View File

@ -69,6 +69,8 @@ zmq::options_t::options_t () :
tcp_keepalive_intvl (-1),
mechanism (ZMQ_NULL),
as_server (0),
gss_principal_nt (ZMQ_GSSAPI_NT_HOSTBASED),
gss_service_principal_nt (ZMQ_GSSAPI_NT_HOSTBASED),
gss_plaintext (false),
socket_id (0),
conflate (false),
@ -509,6 +511,22 @@ int zmq::options_t::setsockopt (int option_, const void *optval_,
return 0;
}
break;
case ZMQ_GSSAPI_PRINCIPAL_NAMETYPE:
if (is_int && (value == ZMQ_GSSAPI_NT_HOSTBASED
|| value == ZMQ_GSSAPI_NT_USER_NAME
|| value == ZMQ_GSSAPI_NT_KRB5_PRINCIPAL)) {
gss_principal_nt = value;
return 0;
}
break;
case ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE:
if (is_int && (value == ZMQ_GSSAPI_NT_HOSTBASED
|| value == ZMQ_GSSAPI_NT_USER_NAME
|| value == ZMQ_GSSAPI_NT_KRB5_PRINCIPAL)) {
gss_service_principal_nt = value;
return 0;
}
break;
#endif
case ZMQ_HANDSHAKE_IVL:

View File

@ -199,6 +199,10 @@ namespace zmq
std::string gss_principal;
std::string gss_service_principal;
// Name types GSSAPI principals
int gss_principal_nt;
int gss_service_principal_nt;
// If true, gss encryption will be disabled
bool gss_plaintext;