Commit 4ae2ffda authored by Luca Boccassi's avatar Luca Boccassi Committed by GitHub

Merge pull request #2545 from garlick/gssapi_nametype

add GSSAPI NAMETYPE socket options
parents 4783605b 48f72844
......@@ -21,7 +21,8 @@ MAN3 = zmq_bind.3 zmq_unbind.3 zmq_connect.3 zmq_disconnect.3 zmq_close.3 \
zmq_atomic_counter_value.3 zmq_atomic_counter_destroy.3
MAN7 = zmq.7 zmq_tcp.7 zmq_pgm.7 zmq_inproc.7 zmq_ipc.7 \
zmq_null.7 zmq_plain.7 zmq_curve.7 zmq_tipc.7 zmq_vmci.7 zmq_udp.7
zmq_null.7 zmq_plain.7 zmq_curve.7 zmq_tipc.7 zmq_vmci.7 zmq_udp.7 \
zmq_gssapi.7
MAN_DOC =
......
......@@ -44,6 +44,26 @@ ZMQ_GSSAPI_PLAINTEXT option. Both the client and server must set this option
to the same value.
PRINCIPAL NAMES
---------------
Principal names specified with the ZMQ_GSSAPI_SERVICE_PRINCIPAL or
ZMQ_GSSAPI_PRINCIPAL options are interpreted as "host based" name types
by default. The ZMQ_GSSAPI_PRINCIPAL_NAMETYPE and
ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE options may be used to change the
name type to one of:
*ZMQ_GSSAPI_NT_HOSTBASED*::
The name should be of the form "service" or "service@hostname",
which will parse into a principal of "service/hostname"
in the local realm. This is the default name type.
*ZMQ_GSSAPI_NT_USER_NAME*::
The name should be a local username, which will parse into a single-component
principal in the local realm.
*ZMQ_GSSAPI_NT_KRB5_PRINCIPAL*::
The name is a principal name string. This name type only works with
the krb5 GSSAPI mechanism.
SEE ALSO
--------
linkzmq:zmq_setsockopt[3]
......
......@@ -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
......
......@@ -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)
......
......@@ -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;
......
......@@ -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;
......
......@@ -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
......
......@@ -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;
}
}
......
......@@ -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:
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment