From 0b43147cd2bc57bb7753c337a83440add88c869f Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Tue, 5 Apr 2011 22:10:00 +0000 Subject: [PATCH] gss_duplicate_name SPI for SPNEGO Preserve attributes when duplicating a name, using the mechanism's implementation of gss_duplicate_name if present, or a loop over the attributes if not. ticket: 6895 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24843 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/gssapi/krb5/gssapi_krb5.c | 1 + src/lib/gssapi/mechglue/g_canon_name.c | 2 +- src/lib/gssapi/mechglue/g_dup_name.c | 4 +- src/lib/gssapi/mechglue/g_glue.c | 115 ++++++++++++++++--------- src/lib/gssapi/mechglue/g_initialize.c | 1 + src/lib/gssapi/mechglue/mglueP.h | 6 ++ src/lib/gssapi/spnego/gssapiP_spnego.h | 8 ++ src/lib/gssapi/spnego/spnego_mech.c | 18 ++++ 8 files changed, 109 insertions(+), 46 deletions(-) diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c index d5a6d1451..a503744e5 100644 --- a/src/lib/gssapi/krb5/gssapi_krb5.c +++ b/src/lib/gssapi/krb5/gssapi_krb5.c @@ -883,6 +883,7 @@ static struct gss_config krb5_mechanism = { #endif krb5_gss_userok, krb5_gss_export_name, + krb5_gss_duplicate_name, krb5_gss_store_cred, krb5_gss_inquire_sec_context_by_oid, krb5_gss_inquire_cred_by_oid, diff --git a/src/lib/gssapi/mechglue/g_canon_name.c b/src/lib/gssapi/mechglue/g_canon_name.c index 51e5ae48e..d17880895 100644 --- a/src/lib/gssapi/mechglue/g_canon_name.c +++ b/src/lib/gssapi/mechglue/g_canon_name.c @@ -141,7 +141,7 @@ gss_name_t *output_name; if ((major_status = gssint_import_internal_name(minor_status, mech_type, - dest_union, + in_union, &dest_union->mech_name))) goto allocation_failure; diff --git a/src/lib/gssapi/mechglue/g_dup_name.c b/src/lib/gssapi/mechglue/g_dup_name.c index 9312de761..85306fcc1 100644 --- a/src/lib/gssapi/mechglue/g_dup_name.c +++ b/src/lib/gssapi/mechglue/g_dup_name.c @@ -109,8 +109,8 @@ gss_name_t *dest_name; } major_status = gssint_import_internal_name(minor_status, - dest_union->mech_type, - dest_union, + src_union->mech_type, + src_union, &dest_union->mech_name); if (major_status != GSS_S_COMPLETE) goto allocation_failure; diff --git a/src/lib/gssapi/mechglue/g_glue.c b/src/lib/gssapi/mechglue/g_glue.c index 3de298cb5..1dcd14795 100644 --- a/src/lib/gssapi/mechglue/g_glue.c +++ b/src/lib/gssapi/mechglue/g_glue.c @@ -283,51 +283,71 @@ OM_uint32 gssint_get_mech_type(OID, token) return (GSS_S_COMPLETE); } - -/* - * Internal routines to get and release an internal mechanism name - */ - -#if 0 static OM_uint32 -import_internal_name_composite(OM_uint32 *minor_status, - gss_mechanism mech, - gss_union_name_t union_name, - gss_name_t *internal_name) +import_internal_attributes(OM_uint32 *minor, + gss_mechanism dmech, + gss_union_name_t sname, + gss_name_t dname) { - OM_uint32 status, tmp; - gss_mechanism name_mech; - gss_buffer_desc composite_name; + OM_uint32 major, tmpMinor; + gss_mechanism smech; + gss_buffer_set_t attrs = GSS_C_NO_BUFFER_SET; + size_t i; - if (mech->gss_import_name == NULL) + if (sname->mech_name == GSS_C_NO_NAME) return (GSS_S_UNAVAILABLE); - name_mech = gssint_get_mechanism(union_name->mech_type); - if (name_mech == NULL) + smech = gssint_get_mechanism (sname->mech_type); + if (smech == NULL) return (GSS_S_BAD_MECH); - if (name_mech->gss_export_name_composite == NULL) + if (smech->gss_inquire_name == NULL || + smech->gss_get_name_attribute == NULL) return (GSS_S_UNAVAILABLE); - composite_name.length = 0; - composite_name.value = NULL; + if (dmech->gss_set_name_attribute == NULL) + return (GSS_S_UNAVAILABLE); - status = (*name_mech->gss_export_name_composite)(minor_status, - union_name->mech_name, - &composite_name); - if (GSS_ERROR(status)) - return (status); + major = smech->gss_inquire_name(minor, sname->mech_name, + NULL, NULL, &attrs); + if (GSS_ERROR(major) || attrs == GSS_C_NO_BUFFER_SET) { + gss_release_buffer_set(&tmpMinor, &attrs); + return (major); + } - status = (*mech->gss_import_name)(minor_status, - &composite_name, - gss_nt_exported_name, - internal_name); + for (i = 0; i < attrs->count; i++) { + int more = -1; - gss_release_buffer(&tmp, &composite_name); + while (more != 0) { + gss_buffer_desc value, display_value; + int authenticated, complete; - return (status); + major = smech->gss_get_name_attribute(minor, sname->mech_name, + &attrs->elements[i], + &authenticated, &complete, + &value, &display_value, + &more); + if (GSS_ERROR(major)) + continue; + + if (authenticated) { + dmech->gss_set_name_attribute(minor, dname, complete, + &attrs->elements[i], &value); + } + + gss_release_buffer(&tmpMinor, &value); + gss_release_buffer(&tmpMinor, &display_value); + } + } + + gss_release_buffer_set(&tmpMinor, &attrs); + + return (GSS_S_COMPLETE); } -#endif + +/* + * Internal routines to get and release an internal mechanism name + */ OM_uint32 gssint_import_internal_name (minor_status, mech_type, union_name, internal_name) @@ -336,24 +356,28 @@ gss_OID mech_type; gss_union_name_t union_name; gss_name_t *internal_name; { - OM_uint32 status; + OM_uint32 status, tmpMinor; gss_mechanism mech; mech = gssint_get_mechanism (mech_type); if (mech == NULL) return (GSS_S_BAD_MECH); -#if 0 - /* Try composite name, it will preserve any extended attributes */ - if (union_name->mech_type && union_name->mech_name) { - status = import_internal_name_composite(minor_status, - mech, - union_name, - internal_name); - if (status == GSS_S_COMPLETE) - return (GSS_S_COMPLETE); + /* + * If we are importing a name for the same mechanism, and the + * mechanism implements gss_duplicate_name, then use that. + */ + if (union_name->mech_name != GSS_C_NO_NAME && + g_OID_equal(union_name->mech_type, mech_type) && + mech->gss_duplicate_name != NULL) { + status = mech->gss_duplicate_name(minor_status, + union_name->mech_name, + internal_name); + if (status != GSS_S_UNAVAILABLE) { + map_error(minor_status, mech); + return (status); + } } -#endif if (mech->gss_import_name == NULL) return (GSS_S_UNAVAILABLE); @@ -362,8 +386,13 @@ gss_name_t *internal_name; union_name->external_name, union_name->name_type, internal_name); - if (status != GSS_S_COMPLETE) + if (status == GSS_S_COMPLETE) { + /* Attempt to round-trip attributes */ + (void) import_internal_attributes(&tmpMinor, mech, + union_name, *internal_name); + } else { map_error(minor_status, mech); + } return (status); } diff --git a/src/lib/gssapi/mechglue/g_initialize.c b/src/lib/gssapi/mechglue/g_initialize.c index e72edd042..60f82fd4b 100644 --- a/src/lib/gssapi/mechglue/g_initialize.c +++ b/src/lib/gssapi/mechglue/g_initialize.c @@ -779,6 +779,7 @@ build_dynamicMech(void *dl, const gss_OID mech_type) GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_pname_to_uid); GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_userok); GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_export_name); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_duplicate_name); GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_store_cred); GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_sec_context_by_oid); GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_cred_by_oid); diff --git a/src/lib/gssapi/mechglue/mglueP.h b/src/lib/gssapi/mechglue/mglueP.h index 2f8e31b7f..fc7013e05 100644 --- a/src/lib/gssapi/mechglue/mglueP.h +++ b/src/lib/gssapi/mechglue/mglueP.h @@ -355,6 +355,12 @@ typedef struct gss_config { const gss_name_t, /* input_name */ gss_buffer_t /* exported_name */ /* */); + OM_uint32 (*gss_duplicate_name) + ( + OM_uint32*, /* minor_status */ + const gss_name_t, /* input_name */ + gss_name_t * /* output_name */ + /* */); OM_uint32 (*gss_store_cred) ( OM_uint32 *, /* minor_status */ diff --git a/src/lib/gssapi/spnego/gssapiP_spnego.h b/src/lib/gssapi/spnego/gssapiP_spnego.h index 3c2edbbdd..29eabbb3c 100644 --- a/src/lib/gssapi/spnego/gssapiP_spnego.h +++ b/src/lib/gssapi/spnego/gssapiP_spnego.h @@ -223,6 +223,14 @@ OM_uint32 spnego_gss_release_name gss_name_t * /* input_name */ ); +OM_uint32 spnego_gss_duplicate_name +( + OM_uint32 *, /* minor_status */ + /* CSTYLED */ + const gss_name_t, /* input_name */ + gss_name_t * /* output_name */ +); + OM_uint32 spnego_gss_inquire_cred ( OM_uint32 *, /* minor_status */ diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c index 01fa8e276..3467ee0d7 100644 --- a/src/lib/gssapi/spnego/spnego_mech.c +++ b/src/lib/gssapi/spnego/spnego_mech.c @@ -246,6 +246,7 @@ static struct gss_config spnego_mechanism = NULL, /* gssd_pname_to_uid */ NULL, /* gss_userok */ NULL, /* gss_export_name */ + spnego_gss_duplicate_name, /* gss_duplicate_name */ NULL, /* gss_store_cred */ spnego_gss_inquire_sec_context_by_oid, /* gss_inquire_sec_context_by_oid */ spnego_gss_inquire_cred_by_oid, /* gss_inquire_cred_by_oid */ @@ -1855,6 +1856,23 @@ spnego_gss_release_name( return (status); } +/*ARGSUSED*/ +OM_uint32 +spnego_gss_duplicate_name( + OM_uint32 *minor_status, + const gss_name_t input_name, + gss_name_t *output_name) +{ + OM_uint32 status; + + dsyslog("Entering duplicate_name\n"); + + status = gss_duplicate_name(minor_status, input_name, output_name); + + dsyslog("Leaving duplicate_name\n"); + return (status); +} + OM_uint32 spnego_gss_inquire_cred( OM_uint32 *minor_status, -- 2.26.2