gss_duplicate_name SPI for SPNEGO
authorGreg Hudson <ghudson@mit.edu>
Tue, 5 Apr 2011 22:10:00 +0000 (22:10 +0000)
committerGreg Hudson <ghudson@mit.edu>
Tue, 5 Apr 2011 22:10:00 +0000 (22:10 +0000)
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
src/lib/gssapi/mechglue/g_canon_name.c
src/lib/gssapi/mechglue/g_dup_name.c
src/lib/gssapi/mechglue/g_glue.c
src/lib/gssapi/mechglue/g_initialize.c
src/lib/gssapi/mechglue/mglueP.h
src/lib/gssapi/spnego/gssapiP_spnego.h
src/lib/gssapi/spnego/spnego_mech.c

index d5a6d14512f897f956dfdf164ec2d2e8ac735a4a..a503744e52dde7c8d9c566e381282bae2dd7593e 100644 (file)
@@ -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,
index 51e5ae48eb5b6b96141658892923dfa26550a41e..d17880895e4ae7a8dece39159cb21f3717aba4cd 100644 (file)
@@ -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;
 
index 9312de761ff0e27ef38ed966c480771d8d9e216e..85306fcc19138b64cad96fadcb7d0c71261da1f6 100644 (file)
@@ -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;
index 3de298cb5764bfb107cc08d450a3b2cafe410f9c..1dcd14795238eaf16f722db38ecf9764ca42f08e 100644 (file)
@@ -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);
 }
index e72edd042cc7d82be0cba583651ed2845a84bf97..60f82fd4bff1c369357d6cda97e0e6fd6aeb1fe9 100644 (file)
@@ -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);
index 2f8e31b7f4ac56a708452070fd1e9969657ae6db..fc7013e053808867b44c6f5979b1027076033a21 100644 (file)
@@ -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 */
index 3c2edbbdde6a8611f1b4b138392baf0023c8db5f..29eabbb3c82a4e73e181912371309479d26f196e 100644 (file)
@@ -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 */
index 01fa8e27667d93855bee4ea71c496f123091ef58..3467ee0d79df8da6a505b5968a91b18e9e62a313 100644 (file)
@@ -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,