summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Howard <lukeh@padl.com>2010-09-20 12:27:08 +0000
committerLuke Howard <lukeh@padl.com>2010-09-20 12:27:08 +0000
commitbabaa573efa8ead826e4a97932d2eeb1670aa6cb (patch)
tree291b5d83248787c51ad0320a23b53c1ae2fa796a
parent4e88a54127d36594eebfe30e97975a1234cc0480 (diff)
downloadkrb5-lhoward/namingexts-mechglue.tar.gz
gss_export_name_composite support for mechanisms that don'tlhoward/namingexts-mechglue
implement it git-svn-id: svn://anonsvn.mit.edu/krb5/users/lhoward/namingexts-mechglue@24334 dc483132-0cff-0310-8789-dd5450dbe970
-rw-r--r--src/lib/gssapi/generic/gssapi.hin2
-rw-r--r--src/lib/gssapi/generic/util_buffer.c8
-rw-r--r--src/lib/gssapi/krb5/gssapi_krb5.c2
-rw-r--r--src/lib/gssapi/mechglue/g_canon_name.c9
-rw-r--r--src/lib/gssapi/mechglue/g_del_name_attr.c3
-rw-r--r--src/lib/gssapi/mechglue/g_dup_name.c8
-rw-r--r--src/lib/gssapi/mechglue/g_get_name_attr.c10
-rw-r--r--src/lib/gssapi/mechglue/g_glue.c81
-rw-r--r--src/lib/gssapi/mechglue/g_imp_name.c137
-rw-r--r--src/lib/gssapi/mechglue/g_inq_name.c23
-rw-r--r--src/lib/gssapi/mechglue/g_nameattr.c205
-rw-r--r--src/lib/gssapi/mechglue/g_set_name_attr.c3
-rw-r--r--src/lib/gssapi/mechglue/mglueP.h7
13 files changed, 339 insertions, 159 deletions
diff --git a/src/lib/gssapi/generic/gssapi.hin b/src/lib/gssapi/generic/gssapi.hin
index fb82e3c4f..354d9f660 100644
--- a/src/lib/gssapi/generic/gssapi.hin
+++ b/src/lib/gssapi/generic/gssapi.hin
@@ -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
diff --git a/src/lib/gssapi/generic/util_buffer.c b/src/lib/gssapi/generic/util_buffer.c
index aabed4bae..62395ec68 100644
--- a/src/lib/gssapi/generic/util_buffer.c
+++ b/src/lib/gssapi/generic/util_buffer.c
@@ -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;
}
diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c
index ba1dbebd7..d902b363d 100644
--- a/src/lib/gssapi/krb5/gssapi_krb5.c
+++ b/src/lib/gssapi/krb5/gssapi_krb5.c
@@ -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,
diff --git a/src/lib/gssapi/mechglue/g_canon_name.c b/src/lib/gssapi/mechglue/g_canon_name.c
index 3d371c0e0..03d36ad5e 100644
--- a/src/lib/gssapi/mechglue/g_canon_name.c
+++ b/src/lib/gssapi/mechglue/g_canon_name.c
@@ -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;
+ }
}
/*
diff --git a/src/lib/gssapi/mechglue/g_del_name_attr.c b/src/lib/gssapi/mechglue/g_del_name_attr.c
index b72ee3b51..a12ac8bbe 100644
--- a/src/lib/gssapi/mechglue/g_del_name_attr.c
+++ b/src/lib/gssapi/mechglue/g_del_name_attr.c
@@ -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;
diff --git a/src/lib/gssapi/mechglue/g_dup_name.c b/src/lib/gssapi/mechglue/g_dup_name.c
index 9312de761..17763bb6e 100644
--- a/src/lib/gssapi/mechglue/g_dup_name.c
+++ b/src/lib/gssapi/mechglue/g_dup_name.c
@@ -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;
diff --git a/src/lib/gssapi/mechglue/g_get_name_attr.c b/src/lib/gssapi/mechglue/g_get_name_attr.c
index a83ebf85b..59c2af842 100644
--- a/src/lib/gssapi/mechglue/g_get_name_attr.c
+++ b/src/lib/gssapi/mechglue/g_get_name_attr.c
@@ -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,
diff --git a/src/lib/gssapi/mechglue/g_glue.c b/src/lib/gssapi/mechglue/g_glue.c
index 3de298cb5..3d2f128c1 100644
--- a/src/lib/gssapi/mechglue/g_glue.c
+++ b/src/lib/gssapi/mechglue/g_glue.c
@@ -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);
diff --git a/src/lib/gssapi/mechglue/g_imp_name.c b/src/lib/gssapi/mechglue/g_imp_name.c
index 5cf713f35..27e99e04b 100644
--- a/src/lib/gssapi/mechglue/g_imp_name.c
+++ b/src/lib/gssapi/mechglue/g_imp_name.c
@@ -36,7 +36,12 @@
#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);
+}
diff --git a/src/lib/gssapi/mechglue/g_inq_name.c b/src/lib/gssapi/mechglue/g_inq_name.c
index b2681ead9..c800df1c8 100644
--- a/src/lib/gssapi/mechglue/g_inq_name.c
+++ b/src/lib/gssapi/mechglue/g_inq_name.c
@@ -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;
}
diff --git a/src/lib/gssapi/mechglue/g_nameattr.c b/src/lib/gssapi/mechglue/g_nameattr.c
index be254d4fb..37c1fa913 100644
--- a/src/lib/gssapi/mechglue/g_nameattr.c
+++ b/src/lib/gssapi/mechglue/g_nameattr.c
@@ -26,13 +26,92 @@
#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,
diff --git a/src/lib/gssapi/mechglue/g_set_name_attr.c b/src/lib/gssapi/mechglue/g_set_name_attr.c
index 1ec72fc27..cd13327f2 100644
--- a/src/lib/gssapi/mechglue/g_set_name_attr.c
+++ b/src/lib/gssapi/mechglue/g_set_name_attr.c
@@ -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;
diff --git a/src/lib/gssapi/mechglue/mglueP.h b/src/lib/gssapi/mechglue/mglueP.h
index eda4e7fc5..a6ebfcbfb 100644
--- a/src/lib/gssapi/mechglue/mglueP.h
+++ b/src/lib/gssapi/mechglue/mglueP.h
@@ -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 */