spnego: Also use mechglue names
This commit is contained in:
@@ -553,6 +553,7 @@ struct gss_mech_compat_desc_struct;
|
||||
|
||||
/* gm_flags */
|
||||
#define GM_USE_MG_CRED 1 /* uses mech glue credentials */
|
||||
#define GM_USE_MG_NAME 2 /* uses mech glue names */
|
||||
|
||||
typedef struct gssapi_mech_interface_desc {
|
||||
unsigned gm_version;
|
||||
|
@@ -182,12 +182,11 @@ gss_accept_sec_context(OM_uint32 *minor_status,
|
||||
* and we have to try all mechs (that we have a cred element
|
||||
* for, if we have a cred).
|
||||
*/
|
||||
ctx = malloc(sizeof(struct _gss_context));
|
||||
ctx = calloc(1, sizeof(struct _gss_context));
|
||||
if (!ctx) {
|
||||
*minor_status = ENOMEM;
|
||||
return (GSS_S_DEFECTIVE_TOKEN);
|
||||
}
|
||||
memset(ctx, 0, sizeof(struct _gss_context));
|
||||
if (mech_oid != GSS_C_NO_OID) {
|
||||
m = ctx->gc_mech = __gss_get_mechanism(mech_oid);
|
||||
if (!m) {
|
||||
@@ -334,11 +333,18 @@ got_one:
|
||||
}
|
||||
|
||||
if (mech_type)
|
||||
*mech_type = mech_ret_type;
|
||||
*mech_type = mech_ret_type;
|
||||
|
||||
if (src_name && src_mn) {
|
||||
if (src_name && src_mn && (ctx->gc_mech->gm_flags & GM_USE_MG_NAME)) {
|
||||
/* Negotiation mechanisms use mechglue names as names */
|
||||
*src_name = src_mn;
|
||||
src_mn = GSS_C_NO_NAME;
|
||||
} else if (src_name && src_mn) {
|
||||
/*
|
||||
* Make a new name and mark it as an MN.
|
||||
*
|
||||
* Note that _gss_create_name() consumes `src_mn' but doesn't
|
||||
* take a pointer, so it can't set it to GSS_C_NO_NAME.
|
||||
*/
|
||||
struct _gss_name *name = _gss_create_name(src_mn, m);
|
||||
|
||||
@@ -348,6 +354,7 @@ got_one:
|
||||
return (GSS_S_FAILURE);
|
||||
}
|
||||
*src_name = (gss_name_t) name;
|
||||
src_mn = GSS_C_NO_NAME;
|
||||
} else if (src_mn) {
|
||||
m->gm_release_name(minor_status, &src_mn);
|
||||
}
|
||||
|
@@ -67,7 +67,11 @@ gss_canonicalize_name(OM_uint32 *minor_status,
|
||||
gss_name_t new_canonical_name;
|
||||
|
||||
*minor_status = 0;
|
||||
*output_name = 0;
|
||||
*output_name = GSS_C_NO_NAME;
|
||||
|
||||
if ((m = __gss_get_mechanism(mech_type)) == NULL ||
|
||||
(m->gm_flags & GM_USE_MG_NAME))
|
||||
return GSS_S_BAD_MECH;
|
||||
|
||||
major_status = _gss_find_mn(minor_status, name, mech_type, &mn);
|
||||
if (major_status)
|
||||
|
@@ -120,7 +120,7 @@ _gss_import_export_name(OM_uint32 *minor_status,
|
||||
return (GSS_S_BAD_NAME);
|
||||
|
||||
m = __gss_get_mechanism(&mech_oid);
|
||||
if (!m)
|
||||
if (!m || !m->gm_import_name)
|
||||
return (GSS_S_BAD_MECH);
|
||||
|
||||
/*
|
||||
@@ -242,6 +242,9 @@ gss_import_name(OM_uint32 *minor_status,
|
||||
HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) {
|
||||
int present = 0;
|
||||
|
||||
if ((m->gm_mech.gm_flags & GM_USE_MG_NAME))
|
||||
continue;
|
||||
|
||||
major_status = gss_test_oid_set_member(minor_status,
|
||||
name_type, m->gm_name_types, &present);
|
||||
|
||||
|
@@ -158,6 +158,7 @@ gss_init_sec_context(OM_uint32 * minor_status,
|
||||
{
|
||||
OM_uint32 major_status;
|
||||
gssapi_mech_interface m;
|
||||
gss_const_name_t mn_inner = GSS_C_NO_NAME;
|
||||
struct _gss_name *name = (struct _gss_name *) target_name;
|
||||
struct _gss_mechanism_name *mn;
|
||||
struct _gss_context *ctx = (struct _gss_context *) *context_handle;
|
||||
@@ -216,12 +217,18 @@ gss_init_sec_context(OM_uint32 * minor_status,
|
||||
/*
|
||||
* Find the MN for this mechanism.
|
||||
*/
|
||||
major_status = _gss_find_mn(minor_status, name, mech_type, &mn);
|
||||
if (major_status != GSS_S_COMPLETE) {
|
||||
if (allocated_ctx)
|
||||
free(ctx);
|
||||
return major_status;
|
||||
}
|
||||
if ((m->gm_flags & GM_USE_MG_NAME)) {
|
||||
mn_inner = target_name;
|
||||
} else {
|
||||
major_status = _gss_find_mn(minor_status, name, mech_type, &mn);
|
||||
if (major_status != GSS_S_COMPLETE) {
|
||||
if (allocated_ctx)
|
||||
free(ctx);
|
||||
return major_status;
|
||||
}
|
||||
if (mn)
|
||||
mn_inner = mn->gmn_name;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have a cred, find the cred for this mechanism.
|
||||
@@ -246,7 +253,7 @@ gss_init_sec_context(OM_uint32 * minor_status,
|
||||
major_status = m->gm_init_sec_context(minor_status,
|
||||
cred_handle,
|
||||
&ctx->gc_ctx,
|
||||
mn ? mn->gmn_name : GSS_C_NO_NAME,
|
||||
mn_inner,
|
||||
mech_type,
|
||||
req_flags,
|
||||
time_req,
|
||||
|
@@ -82,7 +82,11 @@ gss_inquire_context(OM_uint32 *minor_status,
|
||||
return (major_status);
|
||||
}
|
||||
|
||||
if (src_name) {
|
||||
if (src_name && (m->gm_flags & GM_USE_MG_NAME)) {
|
||||
*src_name = src_mn;
|
||||
src_mn = GSS_C_NO_NAME;
|
||||
} else if (src_name && src_mn) {
|
||||
/* _gss_create_name() consumes `src_mn' on success */
|
||||
name = _gss_create_name(src_mn, m);
|
||||
if (!name) {
|
||||
if (mech_type)
|
||||
@@ -92,9 +96,12 @@ gss_inquire_context(OM_uint32 *minor_status,
|
||||
return (GSS_S_FAILURE);
|
||||
}
|
||||
*src_name = (gss_name_t) name;
|
||||
src_mn = GSS_C_NO_NAME;
|
||||
}
|
||||
|
||||
if (targ_name) {
|
||||
if (targ_name && (m->gm_flags & GM_USE_MG_NAME)) {
|
||||
*targ_name = targ_mn;
|
||||
} else if (targ_name && targ_mn) {
|
||||
name = _gss_create_name(targ_mn, m);
|
||||
if (!name) {
|
||||
if (mech_type)
|
||||
@@ -106,6 +113,7 @@ gss_inquire_context(OM_uint32 *minor_status,
|
||||
return (GSS_S_FAILURE);
|
||||
}
|
||||
*targ_name = (gss_name_t) name;
|
||||
targ_mn = GSS_C_NO_NAME;
|
||||
}
|
||||
|
||||
return (GSS_S_COMPLETE);
|
||||
|
@@ -74,7 +74,7 @@ _gss_find_mn(OM_uint32 *minor_status,
|
||||
return GSS_S_BAD_NAME;
|
||||
|
||||
m = __gss_get_mechanism(mech);
|
||||
if (!m)
|
||||
if (!m || !m->gm_import_name)
|
||||
return (GSS_S_BAD_MECH);
|
||||
|
||||
mn = malloc(sizeof(struct _gss_mechanism_name));
|
||||
|
@@ -228,55 +228,6 @@ OM_uint32 GSSAPI_CALLCONV _gss_spnego_unwrap
|
||||
qop_state);
|
||||
}
|
||||
|
||||
OM_uint32 GSSAPI_CALLCONV _gss_spnego_compare_name
|
||||
(OM_uint32 *minor_status,
|
||||
gss_const_name_t name1,
|
||||
gss_const_name_t name2,
|
||||
int * name_equal
|
||||
)
|
||||
{
|
||||
return gss_compare_name(minor_status, name1, name2, name_equal);
|
||||
}
|
||||
|
||||
OM_uint32 GSSAPI_CALLCONV _gss_spnego_display_name
|
||||
(OM_uint32 * minor_status,
|
||||
gss_const_name_t input_name,
|
||||
gss_buffer_t output_name_buffer,
|
||||
gss_OID * output_name_type
|
||||
)
|
||||
{
|
||||
return gss_display_name(minor_status, input_name,
|
||||
output_name_buffer, output_name_type);
|
||||
}
|
||||
|
||||
OM_uint32 GSSAPI_CALLCONV _gss_spnego_import_name
|
||||
(OM_uint32 * minor_status,
|
||||
const gss_buffer_t name_buffer,
|
||||
const gss_OID name_type,
|
||||
gss_name_t * output_name
|
||||
)
|
||||
{
|
||||
return gss_import_name(minor_status, name_buffer,
|
||||
name_type, output_name);
|
||||
}
|
||||
|
||||
OM_uint32 GSSAPI_CALLCONV _gss_spnego_export_name
|
||||
(OM_uint32 * minor_status,
|
||||
gss_const_name_t input_name,
|
||||
gss_buffer_t exported_name
|
||||
)
|
||||
{
|
||||
return gss_export_name(minor_status, input_name, exported_name);
|
||||
}
|
||||
|
||||
OM_uint32 GSSAPI_CALLCONV _gss_spnego_release_name
|
||||
(OM_uint32 * minor_status,
|
||||
gss_name_t * input_name
|
||||
)
|
||||
{
|
||||
return gss_release_name(minor_status, input_name);
|
||||
}
|
||||
|
||||
OM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_context (
|
||||
OM_uint32 * minor_status,
|
||||
gss_const_ctx_id_t context_handle,
|
||||
@@ -469,47 +420,6 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
OM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_mechs_for_name (
|
||||
OM_uint32 * minor_status,
|
||||
gss_const_name_t input_name,
|
||||
gss_OID_set * mech_types
|
||||
)
|
||||
{
|
||||
OM_uint32 ret, junk;
|
||||
|
||||
ret = gss_create_empty_oid_set(minor_status, mech_types);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = gss_add_oid_set_member(minor_status,
|
||||
GSS_SPNEGO_MECHANISM,
|
||||
mech_types);
|
||||
if (ret)
|
||||
gss_release_oid_set(&junk, mech_types);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
OM_uint32 GSSAPI_CALLCONV _gss_spnego_canonicalize_name (
|
||||
OM_uint32 * minor_status,
|
||||
gss_const_name_t input_name,
|
||||
const gss_OID mech_type,
|
||||
gss_name_t * output_name
|
||||
)
|
||||
{
|
||||
/* XXX */
|
||||
return gss_duplicate_name(minor_status, input_name, output_name);
|
||||
}
|
||||
|
||||
OM_uint32 GSSAPI_CALLCONV _gss_spnego_duplicate_name (
|
||||
OM_uint32 * minor_status,
|
||||
gss_const_name_t src_name,
|
||||
gss_name_t * dest_name
|
||||
)
|
||||
{
|
||||
return gss_duplicate_name(minor_status, src_name, dest_name);
|
||||
}
|
||||
|
||||
OM_uint32 GSSAPI_CALLCONV
|
||||
_gss_spnego_wrap_iov(OM_uint32 * minor_status,
|
||||
gss_ctx_id_t context_handle,
|
||||
|
@@ -88,7 +88,7 @@ static gssapi_mech_interface_desc spnego_mech = {
|
||||
GMI_VERSION,
|
||||
"spnego",
|
||||
{6, rk_UNCONST("\x2b\x06\x01\x05\x05\x02") },
|
||||
GM_USE_MG_CRED,
|
||||
GM_USE_MG_CRED | GM_USE_MG_NAME,
|
||||
NULL, /* gm_acquire_cred */
|
||||
NULL, /* gm_release_cred */
|
||||
_gss_spnego_init_sec_context,
|
||||
@@ -102,11 +102,11 @@ static gssapi_mech_interface_desc spnego_mech = {
|
||||
_gss_spnego_unwrap,
|
||||
NULL, /* gm_display_status */
|
||||
NULL, /* gm_indicate_mechs */
|
||||
_gss_spnego_compare_name,
|
||||
_gss_spnego_display_name,
|
||||
_gss_spnego_import_name,
|
||||
_gss_spnego_export_name,
|
||||
_gss_spnego_release_name,
|
||||
NULL, /* gm_compare_name */
|
||||
NULL, /* gm_display_name */
|
||||
NULL, /* gm_import_name */
|
||||
NULL, /* gm_export_name */
|
||||
NULL, /* gm_release_name */
|
||||
NULL, /* gm_inquire_cred */
|
||||
_gss_spnego_inquire_context,
|
||||
_gss_spnego_wrap_size_limit,
|
||||
@@ -114,10 +114,10 @@ static gssapi_mech_interface_desc spnego_mech = {
|
||||
NULL, /* gm_inquire_cred_by_mech */
|
||||
_gss_spnego_export_sec_context,
|
||||
_gss_spnego_import_sec_context,
|
||||
NULL /* _gss_spnego_inquire_names_for_mech */,
|
||||
_gss_spnego_inquire_mechs_for_name,
|
||||
_gss_spnego_canonicalize_name,
|
||||
_gss_spnego_duplicate_name,
|
||||
NULL, /* gm_spnego_inquire_names_for_mech */
|
||||
NULL, /* gm_spnego_inquire_mechs_for_name */
|
||||
NULL, /* gm_spnego_canonicalize_name */
|
||||
NULL, /* gm_spnego_duplicate_name */
|
||||
_gss_spnego_inquire_sec_context_by_oid,
|
||||
NULL, /* gm_inquire_cred_by_oid */
|
||||
_gss_spnego_set_sec_context_option,
|
||||
|
@@ -44,8 +44,10 @@ static char *type_string;
|
||||
static char *mech_string;
|
||||
static char *mechs_string;
|
||||
static char *ret_mech_string;
|
||||
static char *localname_string;
|
||||
static char *client_name;
|
||||
static char *client_password;
|
||||
static char *localname_string;
|
||||
static int dns_canon_flag = -1;
|
||||
static int mutual_auth_flag = 0;
|
||||
static int dce_style_flag = 0;
|
||||
@@ -161,7 +163,7 @@ loop(gss_OID mechoid,
|
||||
int server_done = 0, client_done = 0;
|
||||
int num_loops = 0;
|
||||
OM_uint32 maj_stat, min_stat;
|
||||
gss_name_t gss_target_name;
|
||||
gss_name_t gss_target_name, src_name;
|
||||
gss_buffer_desc input_token, output_token;
|
||||
OM_uint32 flags = 0, ret_cflags, ret_sflags;
|
||||
gss_OID actual_mech_client;
|
||||
@@ -236,7 +238,7 @@ loop(gss_OID mechoid,
|
||||
GSS_C_NO_CREDENTIAL,
|
||||
&output_token,
|
||||
GSS_C_NO_CHANNEL_BINDINGS,
|
||||
NULL,
|
||||
&src_name,
|
||||
&actual_mech_server,
|
||||
&input_token,
|
||||
&ret_sflags,
|
||||
@@ -275,6 +277,49 @@ loop(gss_OID mechoid,
|
||||
errx(1, "mech mismatch");
|
||||
*actual_mech = actual_mech_server;
|
||||
|
||||
if (localname_string) {
|
||||
gss_buffer_desc lname;
|
||||
|
||||
maj_stat = gss_localname(&min_stat, src_name, GSS_C_NO_OID, &lname);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
errx(1, "localname: %s",
|
||||
gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
|
||||
if (verbose_flag)
|
||||
printf("localname: %.*s\n", (int)lname.length,
|
||||
(char *)lname.value);
|
||||
if (lname.length != strlen(localname_string) ||
|
||||
strncmp(localname_string, lname.value, lname.length))
|
||||
errx(1, "localname: expected \"%s\", got \"%.*s\" (1)",
|
||||
localname_string, (int)lname.length, (char *)lname.value);
|
||||
gss_release_buffer(&min_stat, &lname);
|
||||
maj_stat = gss_localname(&min_stat, src_name, actual_mech_server,
|
||||
&lname);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
errx(1, "localname: %s",
|
||||
gssapi_err(maj_stat, min_stat, actual_mech_server));
|
||||
if (lname.length != strlen(localname_string) ||
|
||||
strncmp(localname_string, lname.value, lname.length))
|
||||
errx(1, "localname: expected \"%s\", got \"%.*s\" (2)",
|
||||
localname_string, (int)lname.length, (char *)lname.value);
|
||||
gss_release_buffer(&min_stat, &lname);
|
||||
|
||||
if (!gss_userok(src_name, localname_string))
|
||||
errx(1, "localname is not userok");
|
||||
if (gss_userok(src_name, "nosuchuser:no"))
|
||||
errx(1, "gss_userok() appears broken");
|
||||
}
|
||||
if (verbose_flag) {
|
||||
gss_buffer_desc iname;
|
||||
|
||||
maj_stat = gss_display_name(&min_stat, src_name, &iname, NULL);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
errx(1, "display_name: %s",
|
||||
gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
|
||||
printf("client name: %.*s\n", (int)iname.length, (char *)iname.value);
|
||||
gss_release_buffer(&min_stat, &iname);
|
||||
}
|
||||
gss_release_name(&min_stat, &src_name);
|
||||
|
||||
if (max_loops && num_loops > max_loops)
|
||||
errx(1, "num loops %d was lager then max loops %d",
|
||||
num_loops, max_loops);
|
||||
@@ -593,6 +638,7 @@ static struct getargs args[] = {
|
||||
"server should get a credential", NULL },
|
||||
{"export-import-context",0, arg_flag, &ei_ctx_flag, "test export/import context", NULL },
|
||||
{"export-import-cred",0, arg_flag, &ei_cred_flag, "test export/import cred", NULL },
|
||||
{"localname",0, arg_string, &localname_string, "expected localname for client", "USERNAME"},
|
||||
{"gsskrb5-acceptor-identity", 0, arg_string, &gsskrb5_acceptor_identity, "keytab", NULL },
|
||||
{"session-enctype", 0, arg_string, &session_enctype_string, "enctype", NULL },
|
||||
{"client-time-offset", 0, arg_integer, &client_time_offset, "time", NULL },
|
||||
|
@@ -217,6 +217,7 @@ for mech in krb5 krb5iov spnego spnegoiov; do
|
||||
echo "${mech} no-mutual ${iov}" ; > messages.log
|
||||
${context} --mech-type=${mech} \
|
||||
--wrapunwrap ${iov} \
|
||||
--localname=mapped_user1 \
|
||||
--name-type=hostbased-service host@lucid.test.h5l.se || \
|
||||
{ eval "$testfailed"; }
|
||||
|
||||
|
@@ -4,10 +4,17 @@ include @srcdirabs@/include-krb5.conf
|
||||
default_keytab_name = @objdir@/server.keytab
|
||||
enable-kx509 = yes
|
||||
kx509_store = PEM-FILE:/tmp/cert_%{euid}.pem
|
||||
default_realm = TEST.H5L.SE
|
||||
kuserok = SYSTEM-K5LOGIN:@srcdir@/../kdc/k5login
|
||||
kuserok = USER-K5LOGIN
|
||||
kuserok = SIMPLE
|
||||
|
||||
[realms]
|
||||
TEST.H5L.SE = {
|
||||
kdc = localhost:@port@
|
||||
auth_to_local_names = {
|
||||
user1 = mapped_user1
|
||||
}
|
||||
}
|
||||
|
||||
[kdc]
|
||||
|
@@ -73,6 +73,7 @@ mapped1@TEST2.H5L.SE m1
|
||||
mapped1@TEST3.H5L.SE mapped1
|
||||
mapped2@TEST2.H5L.SE m2
|
||||
mapped2@TEST3.H5L.SE mapped2
|
||||
user1@@TEST.H5L.SE mapped_user1
|
||||
z008213d189aac2b junk
|
||||
z07644c5c50f29d5 junk
|
||||
z094067ad439189c junk
|
||||
|
1
tests/kdc/k5login/mapped_user1
Normal file
1
tests/kdc/k5login/mapped_user1
Normal file
@@ -0,0 +1 @@
|
||||
user1@TEST.H5L.SE
|
Reference in New Issue
Block a user