]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
gss_export_name_composite support for mechanisms that don't lhoward/namingexts-mechglue
authorLuke Howard <lukeh@padl.com>
Mon, 20 Sep 2010 12:27:08 +0000 (12:27 +0000)
committerLuke Howard <lukeh@padl.com>
Mon, 20 Sep 2010 12:27:08 +0000 (12:27 +0000)
implement it

git-svn-id: svn://anonsvn.mit.edu/krb5/users/lhoward/namingexts-mechglue@24334 dc483132-0cff-0310-8789-dd5450dbe970

13 files changed:
src/lib/gssapi/generic/gssapi.hin
src/lib/gssapi/generic/util_buffer.c
src/lib/gssapi/krb5/gssapi_krb5.c
src/lib/gssapi/mechglue/g_canon_name.c
src/lib/gssapi/mechglue/g_del_name_attr.c
src/lib/gssapi/mechglue/g_dup_name.c
src/lib/gssapi/mechglue/g_get_name_attr.c
src/lib/gssapi/mechglue/g_glue.c
src/lib/gssapi/mechglue/g_imp_name.c
src/lib/gssapi/mechglue/g_inq_name.c
src/lib/gssapi/mechglue/g_nameattr.c
src/lib/gssapi/mechglue/g_set_name_attr.c
src/lib/gssapi/mechglue/mglueP.h

index fb82e3c4f5131e84315ab533bdc600fc3a7be184..354d9f660954950bac239200ce892af8ca151fa3 100644 (file)
@@ -408,6 +408,8 @@ GSS_DLLIMP extern gss_OID GSS_C_NT_ANONYMOUS;
  */
 GSS_DLLIMP extern gss_OID GSS_C_NT_EXPORT_NAME;
 
+GSS_DLLIMP extern gss_OID GSS_C_NT_COMPOSITE_EXPORT;
+
 /* Function Prototypes */
 
 OM_uint32 KRB5_CALLCONV
index aabed4baebf026428407686d0bd299276c793a38..62395ec6851ab87bccf403deb07d4504aeaa4532 100644 (file)
@@ -46,6 +46,12 @@ int g_make_string_buffer(const char *str, gss_buffer_t buffer)
 
 int g_duplicate_buffer(const gss_buffer_t src, gss_buffer_t dst)
 {
+    if (src->value == NULL) {
+        dst->value = NULL;
+        dst->length = 0;
+        return 1;
+    }
+
     dst->value = malloc(src->length);
     if (dst->value == NULL) {
         dst->length = 0;
@@ -55,5 +61,5 @@ int g_duplicate_buffer(const gss_buffer_t src, gss_buffer_t dst)
     memcpy(dst->value, src->value, src->length);
     dst->length = src->length;
 
-    return 0;
+    return 1;
 }
index ba1dbebd7c01b40874f57d78ad4658e0e37ef59b..d902b363d91036afd302c1da3c962439f753e578 100644 (file)
@@ -692,7 +692,7 @@ static struct gss_config krb5_mechanism = {
     krb5_gss_get_name_attribute,
     krb5_gss_set_name_attribute,
     krb5_gss_delete_name_attribute,
-    krb5_gss_export_name_composite,
+    NULL,
     krb5_gss_map_name_to_any,
     krb5_gss_release_any_name_mapping,
     krb5_gss_pseudo_random,
index 3d371c0e0422155f2f6efab33bb2e4b6fdf12bde..03d36ad5e4db339c403d321a0e32f5036cc56965 100644 (file)
@@ -97,6 +97,7 @@ gss_name_t *output_name;
                out_union->name_type = 0;
                out_union->external_name = 0;
                out_union->loopback = out_union;
+               out_union->attributes = NULL;
 
                /* Allocate the buffer for the user specified representation */
                if (gssint_create_copy_buffer(in_union->external_name,
@@ -112,7 +113,13 @@ gss_name_t *output_name;
                        goto allocation_failure;
                    }
                }
-
+               if (in_union->attributes) {
+                       major_status = gssint_duplicate_name_attributes(minor_status,
+                                                       in_union->attributes,
+                                                       &out_union->attributes);
+                       if (major_status != GSS_S_COMPLETE)
+                               goto allocation_failure;
+               }
        }
 
        /*
index b72ee3b51745ca921e0f3d4031eca44b83ad75af..a12ac8bbea0b5e9b15637ec3bb41fefe343676dd 100644 (file)
@@ -49,6 +49,9 @@ gss_delete_name_attribute(OM_uint32 *minor_status,
 
     union_name = (gss_union_name_t)name;
 
+    if (union_name->attributes != NULL)
+        return GSS_S_UNAVAILABLE;
+
     if (union_name->mech_type == GSS_C_NO_OID)
         return GSS_S_UNAVAILABLE;
 
index 9312de761ff0e27ef38ed966c480771d8d9e216e..17763bb6ee0b67c4ca471df1f05634e7ff8de354 100644 (file)
@@ -80,6 +80,7 @@ gss_name_t *dest_name;
        dest_union->mech_name = 0;
        dest_union->name_type = 0;
        dest_union->external_name = 0;
+       dest_union->attributes = NULL;
 
        /* Now copy the external representaion */
        if (gssint_create_copy_buffer(src_union->external_name,
@@ -116,6 +117,13 @@ gss_name_t *dest_name;
                        goto allocation_failure;
        }
 
+       if (src_union->attributes) {
+               major_status = gssint_duplicate_name_attributes(minor_status,
+                                                       src_union->attributes,
+                                                       &dest_union->attributes);
+               if (major_status != GSS_S_COMPLETE)
+                       goto allocation_failure;
+       }
 
        dest_union->loopback = dest_union;
        *dest_name = (gss_name_t)dest_union;
index a83ebf85b41c46979261589a5f2b9733b305dff9..59c2af842bfeb6e275048b2334fc3888b7ce9871 100644 (file)
@@ -58,6 +58,14 @@ gss_get_name_attribute(OM_uint32 *minor_status,
         *authenticated = 0;
     if (complete != NULL)
         *complete = 0;
+    if (value != NULL) {
+        value->value = NULL;
+        value->length = 0;
+    }
+    if (display_value != NULL) {
+        display_value->value = NULL;
+        display_value->length = 0;
+    }
 
     *minor_status = 0;
 
@@ -66,7 +74,7 @@ gss_get_name_attribute(OM_uint32 *minor_status,
     if (union_name->attributes != NULL) {
         status = gssint_get_name_attribute(minor_status,
                                            union_name->attributes,
-                                           attr_name,
+                                           attr,
                                            authenticated,
                                            complete,
                                            value,
index 3de298cb5764bfb107cc08d450a3b2cafe410f9c..3d2f128c13957c512052a4d7389d7c11c009e48d 100644 (file)
@@ -288,86 +288,6 @@ OM_uint32 gssint_get_mech_type(OID, token)
  *  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)
-{
-    OM_uint32          status, tmp;
-    gss_mechanism      name_mech;
-    gss_buffer_desc    composite_name;
-
-    if (mech->gss_import_name == NULL)
-       return (GSS_S_UNAVAILABLE);
-
-    name_mech = gssint_get_mechanism(union_name->mech_type);
-    if (name_mech == NULL)
-       return (GSS_S_BAD_MECH);
-
-    if (name_mech->gss_export_name_composite == NULL)
-       return (GSS_S_UNAVAILABLE);
-
-    composite_name.length = 0;
-    composite_name.value = NULL;
-
-    status = (*name_mech->gss_export_name_composite)(minor_status,
-                                                    union_name->mech_name,
-                                                    &composite_name);
-    if (GSS_ERROR(status))
-       return (status);
-
-    status = (*mech->gss_import_name)(minor_status,
-                                     &composite_name,
-                                     gss_nt_exported_name,
-                                     internal_name);
-
-    gss_release_buffer(&tmp, &composite_name);
-
-    return (status);
-}
-#endif
-
-OM_uint32 gssint_import_internal_name (minor_status, mech_type, union_name,
-                               internal_name)
-OM_uint32      *minor_status;
-gss_OID                mech_type;
-gss_union_name_t       union_name;
-gss_name_t     *internal_name;
-{
-    OM_uint32          status;
-    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);
-    }
-#endif
-
-    if (mech->gss_import_name == NULL)
-       return (GSS_S_UNAVAILABLE);
-
-    status = mech->gss_import_name(minor_status,
-                                  union_name->external_name,
-                                  union_name->name_type,
-                                  internal_name);
-    if (status != GSS_S_COMPLETE)
-       map_error(minor_status, mech);
-
-    return (status);
-}
-
 OM_uint32 gssint_export_internal_name(minor_status, mech_type,
                                     internal_name, name_buf)
     OM_uint32          *minor_status;
@@ -595,6 +515,7 @@ OM_uint32 gssint_convert_name_to_union_name(minor_status, mech,
     union_name->mech_name = internal_name;
     union_name->name_type = 0;
     union_name->external_name = 0;
+    union_name->attributes = NULL;
 
     major_status = generic_gss_copy_oid(minor_status, &mech->mech_type,
                                        &union_name->mech_type);
index 5cf713f354859d9dc60d12b681aa29c2f31f7974..27e99e04b43c99ec1bfcd4e7f1d617b34aae1ebe 100644 (file)
 #include <errno.h>
 
 /* local function to import GSS_C_EXPORT_NAME names */
-static OM_uint32 importExportName(OM_uint32 *, gss_union_name_t);
+static OM_uint32
+importExportName(OM_uint32 *minor_status,
+                gss_union_name_t union_name,
+                gss_OID *mech_type,
+                gss_name_t *mech_name,
+                gss_name_attribute_t *attrs);
 
 static OM_uint32
 val_imp_name_args(
@@ -109,6 +114,7 @@ gss_name_t *                output_name;
     union_name->mech_name = 0;
     union_name->name_type = 0;
     union_name->external_name = 0;
+    union_name->attributes = NULL;
 
     /*
      * All we do here is record the external name and name_type.
@@ -144,8 +150,13 @@ gss_name_t *               output_name;
      * do however make this an MN for names of GSS_C_NT_EXPORT_NAME type.
      */
     if (input_name_type != GSS_C_NULL_OID &&
-       g_OID_equal(input_name_type, GSS_C_NT_EXPORT_NAME)) {
-       major_status = importExportName(minor_status, union_name);
+       (g_OID_equal(input_name_type, GSS_C_NT_EXPORT_NAME) ||
+        g_OID_equal(input_name_type, GSS_C_NT_COMPOSITE_EXPORT))) {
+       major_status = importExportName(minor_status,
+                                       union_name,
+                                       &union_name->mech_type,
+                                       &union_name->mech_name,
+                                       &union_name->attributes);
        if (major_status != GSS_S_COMPLETE)
            goto allocation_failure;
     }
@@ -182,9 +193,16 @@ importCompositeName(OM_uint32 *minor_status,
     gss_name_attribute_t head = NULL, *pNext = &head;
     size_t remain = name_buf->length;
     unsigned char *p = (unsigned char *)name_buf->value;
+    ssize_t attrCount;
 
     *pAttributes = NULL;
 
+    if (remain < 4)
+        return GSS_S_BAD_NAME;
+
+    TREAD_INT(p, attrCount, 1);
+    remain -= 4;
+
     do {
         gss_name_attribute_t attr;
 
@@ -192,8 +210,13 @@ importCompositeName(OM_uint32 *minor_status,
                                                    &p, &remain);
         if (GSS_ERROR(status))
             break;
+
+        attrCount--;
     } while (remain != 0);
 
+    if (attrCount != 0)
+        status = GSS_S_BAD_NAME;
+
     if (GSS_ERROR(status))
         gssint_release_name_attributes(&tmpMinor, &head);
     else
@@ -210,15 +233,18 @@ static const unsigned int mechOidLenLen = 2;
 static const unsigned int nameTypeLenLen = 2;
 
 static OM_uint32
-importExportName(minor, unionName)
-    OM_uint32 *minor;
-    gss_union_name_t unionName;
+importExportName(OM_uint32 *minor,
+                gss_union_name_t unionName,
+                gss_OID *mech_type,
+                gss_name_t *mech_name,
+                gss_name_attribute_t *attributes)
 {
     gss_OID_desc mechOid;
     gss_buffer_desc expName;
     unsigned char *buf;
     gss_mechanism mech;
-    OM_uint32 major, mechOidLen, nameLen, curLength;
+    OM_uint32 major, tmpMinor;
+    OM_uint32 mechOidLen, nameLen, curLength;
     unsigned int bytes;
     int composite;
 
@@ -236,6 +262,15 @@ importExportName(minor, unionName)
        return (GSS_S_DEFECTIVE_TOKEN);
 
     composite = (buf[1] == 0x02);
+    /*
+     * MIT 1.8 emits composite tokens with GSS_C_NT_EXPORT, because
+     * GSS_C_NT_COMPOSITE_EXPORT was not defined then. So accept
+     * this, but if the new OID is specified, require composite
+     * tokens.
+     */
+    if (g_OID_equal(unionName->name_type, GSS_C_NT_COMPOSITE_EXPORT) &&
+       composite == 0)
+       return (GSS_S_DEFECTIVE_TOKEN);
 
     buf += expNameTokIdLen;
 
@@ -286,15 +321,20 @@ importExportName(minor, unionName)
      */
     if (composite ? mech->gss_export_name_composite : mech->gss_export_name) {
        major = mech->gss_import_name(minor,
-                                     &expName, (gss_OID)GSS_C_NT_EXPORT_NAME,
-                                     &unionName->mech_name);
+                                     &expName,
+                                     composite
+                                       ? (gss_OID)GSS_C_NT_COMPOSITE_EXPORT
+                                       : (gss_OID)GSS_C_NT_EXPORT_NAME,
+                                     mech_name);
        if (major != GSS_S_COMPLETE)
            map_error(minor, mech);
        else {
            major = generic_gss_copy_oid(minor, &mechOid,
-                                        &unionName->mech_type);
-           if (major != GSS_S_COMPLETE)
+                                        mech_type);
+           if (major != GSS_S_COMPLETE) {
+               gssint_release_internal_name(&tmpMinor, &mechOid, mech_name);
                map_errcode(minor);
+           }
        }
        return (major);
     }
@@ -325,7 +365,9 @@ importExportName(minor, unionName)
     /*
      * we use < here because bad code in rpcsec_gss rounds up exported
      * name token lengths and pads with nulls, otherwise != would be
-     * appropriate
+     * appropriate, for the non-composite name case (the composite
+     * name is appended to the end of the simple name, so an equality
+     * check would be inappropriate)
      */
     curLength += nameLen;   /* this is the total length */
     if (expName.length < curLength)
@@ -384,25 +426,80 @@ importExportName(minor, unionName)
     expName.length = nameLen;
     expName.value = nameLen ? (void *)buf : NULL;
     major = mech->gss_import_name(minor, &expName,
-                                 GSS_C_NULL_OID, &unionName->mech_name);
+                                 GSS_C_NULL_OID, mech_name);
     if (major != GSS_S_COMPLETE) {
        map_error(minor, mech);
        return (major);
     }
 
-    major = generic_gss_copy_oid(minor, &mechOid, &unionName->mech_type);
+    major = generic_gss_copy_oid(minor, &mechOid, mech_type);
     if (major != GSS_S_COMPLETE) {
        map_errcode(minor);
+       gssint_release_internal_name(&tmpMinor, &mechOid, mech_name);
+       return (major);
     }
 
-    if (composite) {
-        expName.length = curLength - nameLen;
-        expName.value = buf + nameLen;
+    if (composite && attributes != NULL) {
+       expName.length = unionName->external_name->length - curLength;
+       expName.value = buf + nameLen;
 
-        major = importCompositeName(minor, &expName, &unionName->attributes);
-        if (major != GSS_S_COMPLETE)
-            return major;
+       major = importCompositeName(minor, &expName, attributes);
+       if (major != GSS_S_COMPLETE) {
+           gssint_release_internal_name(&tmpMinor, &mechOid, mech_name);
+           return (major);
+       }
     }
 
     return major;
 } /* importExportName */
+
+OM_uint32
+gssint_import_internal_name(OM_uint32 *minor_status,
+                           gss_OID mech_type,
+                           gss_union_name_t union_name,
+                           gss_name_t *internal_name)
+{
+    OM_uint32           status, tmpMinor;
+    gss_mechanism       mech;
+
+    /*
+     * This path allows us to take advantage of internal import-
+     * export name semantics (for use with self-exported composite
+     * names). Otherwise, a mechanism that supports naming extensions
+     * but not gss_export_name_composite will fail parsing a
+     * composite name.
+     */
+    if (union_name->name_type != GSS_C_NULL_OID &&
+       (g_OID_equal(union_name->name_type, GSS_C_NT_EXPORT_NAME) ||
+        g_OID_equal(union_name->name_type, GSS_C_NT_COMPOSITE_EXPORT))) {
+       gss_OID actualMech = GSS_C_NO_OID;
+       status = importExportName(minor_status,
+                                 union_name,
+                                 &actualMech,
+                                 internal_name,
+                                 NULL);
+       if (status == GSS_S_COMPLETE &&
+           !g_OID_equal(mech_type, actualMech)) {
+           gssint_release_internal_name(&tmpMinor, mech_type, internal_name);
+           status = GSS_S_BAD_MECH;
+       }
+
+       return (status);
+    }
+
+    mech = gssint_get_mechanism (mech_type);
+    if (mech == NULL)
+        return (GSS_S_BAD_MECH);
+
+    if (mech->gss_import_name == NULL)
+        return (GSS_S_UNAVAILABLE);
+
+    status = mech->gss_import_name(minor_status,
+                                   union_name->external_name,
+                                   union_name->name_type,
+                                   internal_name);
+    if (status != GSS_S_COMPLETE)
+        map_error(minor_status, mech);
+
+    return (status);
+}
index b2681ead920d28dd265b010bb13a7d957161a2f8..c800df1c84b361631a579eb6167df6ba2e1de863 100644 (file)
@@ -50,16 +50,35 @@ gss_inquire_name(OM_uint32 *minor_status,
     if (MN_mech != NULL)
         *MN_mech = GSS_C_NO_OID;
 
+    if (name_is_MN != NULL)
+        name_is_MN = 0;
+
     if (attrs != NULL)
         *attrs = GSS_C_NO_BUFFER_SET;
 
     *minor_status = 0;
     union_name = (gss_union_name_t)name;
 
+    if (union_name->attributes != NULL) {
+        gss_name_attribute_t attr;
+
+        status = GSS_S_COMPLETE;
+
+        for (attr = union_name->attributes; attr != NULL; attr = attr->next) {
+            status = gss_add_buffer_set_member(minor_status, &attr->attribute,
+                                               attrs);
+            if (GSS_ERROR(status))
+                break;
+        }
+
+        if (GSS_ERROR(status))
+            gss_release_buffer_set(&tmp, attrs);
+
+        return status;
+    }
+
     if (union_name->mech_type == GSS_C_NO_OID) {
         /* We don't yet support non-mechanism attributes */
-        if (name_is_MN != NULL)
-            name_is_MN = 0;
         *minor_status = 0;
         return GSS_S_COMPLETE;
     }
index be254d4fbbc6759972d059fd2ce0996fd2e908ba..37c1fa913f1f165ea8477aab9419cfbf6d46bf79 100644 (file)
 
 #include "mglueP.h"
 
+static OM_uint32
+duplicateNameAttribute(OM_uint32 *minor_status,
+                       gss_name_attribute_t src,
+                       gss_name_attribute_t *pDst)
+{
+    OM_uint32 tmpMinor;
+    gss_name_attribute_t dst;
+    size_t i;
+
+    dst = calloc(1, sizeof(gss_name_attribute_desc));
+    if (dst == NULL)
+        goto alloc_fail;
+
+    if (!g_duplicate_buffer(&src->attribute, &dst->attribute))
+        goto alloc_fail;
+
+    dst->authenticated = src->authenticated;
+    dst->complete = src->complete;
+
+    if (src->values.count > 0) {
+        dst->values.elements = calloc(src->values.count,
+                                      sizeof(gss_buffer_desc));
+        if (dst->values.elements == NULL)
+            goto alloc_fail;
+
+        dst->display_values.elements = calloc(src->values.count,
+                                              sizeof(gss_buffer_desc));
+        if (dst->display_values.elements == NULL)
+            goto alloc_fail;
+
+        for (i = 0; i < src->values.count; i++) {
+            if (!g_duplicate_buffer(&src->values.elements[i],
+                                    &dst->values.elements[i]))
+                goto alloc_fail;
+            if (!g_duplicate_buffer(&src->display_values.elements[i],
+                                    &dst->display_values.elements[i]))
+                goto alloc_fail;
+        }
+    }
+
+    *pDst = dst;
+    return GSS_S_COMPLETE;
+
+alloc_fail:
+    gssint_release_name_attribute(&tmpMinor, &dst);
+    *minor_status = ENOMEM;
+    return GSS_S_FAILURE;
+}
+
+OM_uint32
+gssint_duplicate_name_attributes(OM_uint32 *minor_status,
+                                 gss_name_attribute_t srcAttrs,
+                                 gss_name_attribute_t *pDstAttrs)
+{
+    gss_name_attribute_t srcAttr;
+    gss_name_attribute_t dstAttrHead = NULL, *pDstAttr = &dstAttrHead;
+    OM_uint32 status, tmpMinor;
+
+    for (srcAttr = srcAttrs; srcAttr != NULL; srcAttr = srcAttr->next) {
+        gss_name_attribute_t dstAttr;
+
+        status = duplicateNameAttribute(minor_status, srcAttr, &dstAttr);
+        if (GSS_ERROR(status))
+            goto cleanup;
+
+        *pDstAttr = dstAttr;
+        pDstAttr = &dstAttr->next;
+    }
+
+    *pDstAttrs = dstAttrHead;
+    status = GSS_S_COMPLETE;
+
+cleanup:
+    if (GSS_ERROR(status))
+        gssint_release_name_attributes(&tmpMinor, &dstAttrHead);
+
+    return status;
+}
+
 OM_uint32
 gssint_release_name_attribute(OM_uint32 *minor_status,
-                              gss_name_attribute_t *pAttribute)
+                              gss_name_attribute_t *pAttr)
 {
     OM_uint32 tmpMinor;
     size_t i;
-    gss_name_attribute_t attr = *pAttribute;
+    gss_name_attribute_t attr = *pAttr;
 
     if (attr != NULL) {
         gss_release_buffer(&tmpMinor, &attr->attribute);
@@ -42,7 +121,7 @@ gssint_release_name_attribute(OM_uint32 *minor_status,
             gss_release_buffer(&tmpMinor, &attr->display_values.elements[i]);
         }
         free(attr);
-        *pAttribute = NULL;
+        *pAttr = NULL;
     }
 
     return GSS_S_COMPLETE;
@@ -62,22 +141,8 @@ gssint_get_name_attribute(OM_uint32 *minor_status,
     int i = *more;
     OM_uint32 tmpMinor;
 
-    if (authenticated != NULL)
-        *authenticated = 0;
-    if (complete != NULL)
-        *complete = 0;
     *more = 0;
 
-    if (value != NULL) {
-        value->value = NULL;
-        value->length = 0;
-    }
-
-    if (display_value != NULL) {
-        display_value->value = NULL;
-        display_value->length = 0;
-    }
-
     for (attr = attributes; attr != NULL; attr = attr->next) {
         if (attr->attribute.length == attr_name->length &&
             !memcmp(attr->attribute.value, attr_name->value, attr_name->length)) {
@@ -94,25 +159,51 @@ gssint_get_name_attribute(OM_uint32 *minor_status,
     else if ((size_t)i >= attr->values.count)
         return GSS_S_UNAVAILABLE;
 
-    if (value != NULL &&
-        !g_duplicate_buffer(&attr->values.elements[i], value)) {
-        *minor_status = ENOMEM;
-        return GSS_S_FAILURE;
-    }
-    if (display_value != NULL &&
-        !g_duplicate_buffer(&attr->display_values.elements[i], display_value)) {
-        gss_release_buffer(&tmpMinor, value);
-        return GSS_S_FAILURE;
+    if (attr->values.count > 0) {
+        if (value != NULL &&
+            !g_duplicate_buffer(&attr->values.elements[i], value)) {
+            *minor_status = ENOMEM;
+            return GSS_S_FAILURE;
+        }
+        if (display_value != NULL &&
+            !g_duplicate_buffer(&attr->display_values.elements[i],
+                                display_value)) {
+            gss_release_buffer(&tmpMinor, value);
+            return GSS_S_FAILURE;
+        }
     }
-    *authenticated = attr->authenticated;
-    *complete = attr->complete;
 
+    if (authenticated != NULL)
+        *authenticated = attr->authenticated;
+    if (complete != NULL)
+        *complete = attr->complete;
     if (attr->values.count > (size_t)++i)
         *more = i;
 
     return GSS_S_COMPLETE;
 }
 
+/*
+ * An encoded attribute looks like
+ *
+ *      uint32      attribute name length
+ *      char[]      attribute name data
+ *      uint32      attribute flags
+ *      uint32      value count
+ *      value[]     values
+ *
+ * where a value is:
+ *
+ *      uint32      value length
+ *      char[]      value data
+ *      uint32      display value length
+ *      char[]      display value data
+ *
+ * The encoding of a set of attributes consists of the attribute
+ * count following by the encoding of each attribute.
+ *
+ * All integers are big-endian.
+ */
 static size_t
 nameAttributeSize(gss_name_attribute_t attr)
 {
@@ -143,6 +234,8 @@ nameAttributeExternalize(OM_uint32 *minor_status,
     unsigned char *p = *pBuffer;
     size_t i, remain = *pRemain;
 
+    assert(remain >= nameAttributeSize(attr));
+
     if (attr->authenticated)
         flags |= NAME_FLAG_AUTHENTICATED;
     if (attr->complete)
@@ -171,49 +264,47 @@ nameAttributeExternalize(OM_uint32 *minor_status,
     return GSS_S_COMPLETE;
 }
 
-#define CHECK_REMAIN(len)   do {    \
-    if ((remain) < len) {           \
-        status = GSS_S_BAD_NAME;    \
-        goto cleanup;               \
-    }                               \
-  } while (0)
-
 static OM_uint32
 internalizeBuffer(OM_uint32 *minor_status,
                   gss_buffer_desc *buffer,
                   unsigned char **pBuffer,
                   size_t *pRemain)
 {
-    OM_uint32 status;
     unsigned char *p = *pBuffer;
     size_t remain = *pRemain;
 
-    CHECK_REMAIN(4);
+    if (remain < 4)
+        return GSS_S_BAD_NAME;
+
     TREAD_INT(p, buffer->length, 1);
     remain -= 4;
 
-    CHECK_REMAIN(buffer->length);
+    if (remain < buffer->length)
+        return GSS_S_BAD_NAME;
 
     /* Attribute name */
     buffer->value = malloc(buffer->length + 1);
     if (buffer->value == NULL) {
         *minor_status = ENOMEM;
-        status = GSS_S_FAILURE;
-        goto cleanup;
+        return GSS_S_FAILURE;
     }
+
     memcpy(buffer->value, p, buffer->length);
     ((char *)buffer->value)[buffer->length] = '\0';
 
-    p += buffer->length;
-    remain -= buffer->length;
+    *pBuffer = p + buffer->length;
+    *pRemain = remain - buffer->length;
 
-    *pBuffer = p;
-    *pRemain = remain;
-
-cleanup:
-    return status;
+    return GSS_S_COMPLETE;
 }
 
+#define CHECK_REMAIN(len)   do {    \
+    if ((remain) < len) {           \
+        status = GSS_S_BAD_NAME;    \
+        goto cleanup;               \
+    }                               \
+  } while (0)
+
 OM_uint32
 gssint_name_attribute_internalize(OM_uint32 *minor_status,
                                   gss_name_attribute_t *pAttr,
@@ -306,7 +397,7 @@ addNameAttribute(OM_uint32 *minor_status,
                  gss_mechanism mech,
                  gss_name_t internal_name,
                  gss_buffer_t attribute_name,
-                 gss_name_attribute_t *pAttribute,
+                 gss_name_attribute_t *pAttr,
                  gss_name_attribute_t **pNext)
 {
     gss_name_attribute_t attr = NULL;
@@ -321,6 +412,12 @@ addNameAttribute(OM_uint32 *minor_status,
         goto cleanup;
     }
 
+    if (!g_duplicate_buffer(attribute_name, &attr->attribute)) {
+        *minor_status = ENOMEM;
+        status = GSS_S_FAILURE;
+        goto cleanup;
+    }
+
     values = &attr->values;
     display_values = &attr->display_values;
 
@@ -357,7 +454,7 @@ addNameAttribute(OM_uint32 *minor_status,
         assert(display_values == &attr->display_values);
     }
 
-    *pAttribute = attr;
+    *pAttr = attr;
 
     if (pNext != NULL) {
         assert(*pNext != NULL);
@@ -375,9 +472,9 @@ cleanup:
 
 OM_uint32
 gssint_release_name_attributes(OM_uint32 *minor_status,
-                               gss_name_attribute_t *pAttributes)
+                               gss_name_attribute_t *pAttrs)
 {
-    gss_name_attribute_t attributes = *pAttributes;
+    gss_name_attribute_t attributes = *pAttrs;
     OM_uint32 tmpMinor;
 
     if (attributes != NULL) {
@@ -389,7 +486,7 @@ gssint_release_name_attributes(OM_uint32 *minor_status,
             attributes = next;
         } while (attributes != NULL);
 
-        *pAttributes = NULL;
+        *pAttrs = NULL;
     }
 
     return GSS_S_COMPLETE;
@@ -467,6 +564,7 @@ gssint_export_internal_name_composite(OM_uint32 *minor_status,
     }
 
     remain = expName.length;
+    remain += 4; /* attribute count */
 
     for (i = 0; i < attrNames->count; i++) {
         status = addNameAttribute(minor_status,
@@ -497,6 +595,9 @@ gssint_export_internal_name_composite(OM_uint32 *minor_status,
     p += expName.length;
     remain -= expName.length;
 
+    TWRITE_INT(p, attrNames->count, 1);
+    remain -= 4;
+
     for (attr = head; attr != NULL; attr = head->next) {
         status = nameAttributeExternalize(minor_status,
                                           attr,
index 1ec72fc2717335d1fa6c59787f4636768a7a638a..cd13327f2ddc4ec0387e74ddfefe18c01ded98f4 100644 (file)
@@ -51,6 +51,9 @@ gss_set_name_attribute(OM_uint32 *minor_status,
 
     union_name = (gss_union_name_t)name;
 
+    if (union_name->attributes != NULL)
+        return GSS_S_UNAVAILABLE;
+
     if (union_name->mech_type == GSS_C_NO_OID)
         return GSS_S_UNAVAILABLE;
 
index eda4e7fc542aa66f3384c3410b47968e11404e45..a6ebfcbfb739ea6146f67e6fcc3e10aad1280005 100644 (file)
@@ -51,7 +51,7 @@ typedef struct gss_name_struct {
        gss_OID                 name_type;
        gss_buffer_t            external_name;
        /*
-        * These last two fields are only filled in for mechanism
+        * These next two fields are only filled in for mechanism
         * names.
         */
        gss_OID                 mech_type;
@@ -824,4 +824,9 @@ gssint_export_internal_name_composite(OM_uint32 *minor_status,
                                       const gss_name_t internal_name,
                                       gss_buffer_t name_buf);
 
+OM_uint32
+gssint_duplicate_name_attributes(OM_uint32 *minor_status,
+                                 gss_name_attribute_t srcAttrs,
+                                 gss_name_attribute_t *pDstAttrs);
+
 #endif /* _GSS_MECHGLUEP_H */