From: Luke Howard Date: Wed, 8 Sep 2010 15:52:03 +0000 (+0200) Subject: Add gss_import_name skeleton X-Git-Tag: vm/20110310~383 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mech_eap.orig;a=commitdiff_plain;h=aa0df2f91c1dcede24c7dbf60d71414ca157dd51 Add gss_import_name skeleton --- diff --git a/import_name.c b/import_name.c index 152bb21..bceefcd 100644 --- a/import_name.c +++ b/import_name.c @@ -38,5 +38,6 @@ gss_import_name(OM_uint32 *minor, gss_OID input_name_type, gss_name_t *output_name) { - GSSEAP_NOT_IMPLEMENTED; + return gssEapImportName(minor, import_name_buffer, + input_name_type, output_name); } diff --git a/util.h b/util.h index 52a585a..4f0f98a 100644 --- a/util.h +++ b/util.h @@ -176,6 +176,10 @@ OM_uint32 gssEapExportName(OM_uint32 *minor, const gss_name_t name, gss_buffer_t exportedName, int composite); +OM_uint32 gssEapImportName(OM_uint32 *minor, + const gss_buffer_t input_name_buffer, + gss_OID input_name_type, + gss_name_t *output_name); /* util_oid.c */ OM_uint32 @@ -193,10 +197,15 @@ decomposeOid(OM_uint32 *minor_status, int *suffix) ; static inline int -oidEqual(const gss_OID_desc *o1, const gss_OID_desc *o2) +oidEqual(const gss_OID_desc *o1, const gss_OID_desc *o2) { - return (o1->length == o2->length && - memcmp(o1->elements, o2->elements, o1->length) == 0); + if (o1 == GSS_C_NO_OID) + return (o2 == GSS_C_NO_OID); + else if (o2 == GSS_C_NO_OID) + return (o1 == GSS_C_NO_OID); + else + return (o1->length == o2->length && + memcmp(o1->elements, o2->elements, o1->length) == 0); } /* util_ordering.c */ @@ -358,4 +367,24 @@ makeStringBuffer(OM_uint32 *minor, return GSS_S_COMPLETE; } +static OM_uint32 +bufferToString(OM_uint32 *minor, + const gss_buffer_t buffer, + char **pString) +{ + char *s; + + s = GSSEAP_MALLOC(buffer->length + 1); + if (s == NULL) { + *minor = ENOMEM; + return GSS_S_FAILURE; + } + memcpy(s, buffer->value, buffer->length); + s[buffer->length] = '\0'; + + *pString = s; + + *minor = 0; + return GSS_S_COMPLETE; +} #endif /* _UTIL_H_ */ diff --git a/util_name.c b/util_name.c index e3898ec..abe60c0 100644 --- a/util_name.c +++ b/util_name.c @@ -118,6 +118,198 @@ gssEapReleaseName(OM_uint32 *minor, gss_name_t *pName) return GSS_S_COMPLETE; } +static OM_uint32 +krbPrincipalToName(OM_uint32 *minor, + krb5_principal *principal, + gss_name_t *pName) +{ + OM_uint32 major; + gss_name_t name; + + major = gssEapAllocName(minor, &name); + if (GSS_ERROR(major)) + return major; + + name->krbPrincipal = *principal; + *principal = NULL; + + *minor = 0; + return GSS_S_COMPLETE; +} + +static OM_uint32 +importServiceName(OM_uint32 *minor, + const gss_buffer_t nameBuffer, + gss_name_t *pName) +{ + OM_uint32 major, tmpMinor; + krb5_context krbContext; + krb5_principal krbPrinc; + char *service, *host; + + GSSEAP_KRB_INIT(&krbContext); + + major = bufferToString(minor, nameBuffer, &service); + if (GSS_ERROR(major)) + return major; + + host = strchr(service, '@'); + if (host != NULL) { + *host = '\0'; + host++; + } + + /* XXX this is probably NOT what we want to be doing */ + *minor = krb5_sname_to_principal(krbContext, host, service, + KRB5_NT_SRV_HST, &krbPrinc); + if (*minor != 0) { + GSSEAP_FREE(service); + return GSS_S_FAILURE; + } + + major = krbPrincipalToName(minor, &krbPrinc, pName); + if (GSS_ERROR(major)) { + krb5_free_principal(krbContext, krbPrinc); + } + + GSSEAP_FREE(service); + return major; +} + +static OM_uint32 +importUserName(OM_uint32 *minor, + const gss_buffer_t nameBuffer, + gss_name_t *pName) +{ + OM_uint32 major, tmpMinor; + krb5_context krbContext; + krb5_principal krbPrinc; + char *nameString; + + GSSEAP_KRB_INIT(&krbContext); + + major = bufferToString(minor, nameBuffer, &nameString); + if (GSS_ERROR(major)) + return major; + + *minor = krb5_parse_name(krbContext, nameString, &krbPrinc); + if (*minor != 0) { + GSSEAP_FREE(nameString); + return GSS_S_FAILURE; + } + + major = krbPrincipalToName(minor, &krbPrinc, pName); + if (GSS_ERROR(major)) { + krb5_free_principal(krbContext, krbPrinc); + } + + GSSEAP_FREE(nameString); + return major; +} + +static OM_uint32 +importExportedName(OM_uint32 *minor, + const gss_buffer_t nameBuffer, + gss_name_t *pName) +{ + OM_uint32 major, tmpMinor; + krb5_context krbContext; + unsigned char *p; + int composite = 0; + size_t len, remain; + gss_buffer_desc buf; + + GSSEAP_KRB_INIT(&krbContext); + + p = (unsigned char *)nameBuffer->value; + remain = nameBuffer->length; + + if (remain < 6 + GSS_EAP_MECHANISM->length + 4) + return GSS_S_BAD_NAME; + + if (*p++ != 0x04) + return GSS_S_BAD_NAME; + + switch (*p++) { + case 0x02: + composite = 1; + break; + case 0x01: + break; + default: + return GSS_S_BAD_NAME; + break; + } + remain -= 2; + + len = load_uint16_be(p); + if (len != 2 + GSS_EAP_MECHANISM->length) + return GSS_S_BAD_NAME; + p += 2; + remain -= 2; + + if (*p++ != 0x06) + return GSS_S_BAD_NAME; + if (*p++ != GSS_EAP_MECHANISM->length) + return GSS_S_BAD_MECH; + remain -= 2; + + if (memcmp(p, GSS_EAP_MECHANISM->elements, GSS_EAP_MECHANISM->length)) + return GSS_S_BAD_MECH; + p += GSS_EAP_MECHANISM->length; + remain -= GSS_EAP_MECHANISM->length; + + len = load_uint32_be(p); + p += 4; + + if (remain < len) + return GSS_S_BAD_NAME; + + buf.length = len; + buf.value = p; + + p += len; + remain -= len; + + if (composite == 0 && remain != 0) + return GSS_S_BAD_NAME; + + major = importUserName(minor, &buf, pName); + if (GSS_ERROR(major)) + return major; + + /* XXX TODO composite handling */ + + return GSS_S_COMPLETE; +} + +OM_uint32 gssEapImportName(OM_uint32 *minor, + const gss_buffer_t nameBuffer, + gss_OID nameType, + gss_name_t *name) +{ + OM_uint32 major, tmpMinor; + + *name = GSS_C_NO_NAME; + + if (nameType == GSS_C_NULL_OID || + oidEqual(nameType, GSS_C_NT_USER_NAME) || + oidEqual(nameType, GSS_EAP_NT_PRINCIPAL_NAME)) + major = importUserName(minor, nameBuffer, name); + else if (oidEqual(nameType, GSS_C_NT_HOSTBASED_SERVICE) || + oidEqual(nameType, GSS_C_NT_HOSTBASED_SERVICE_X)) + major = importServiceName(minor, nameBuffer, name); + else if (oidEqual(nameType, GSS_C_NT_EXPORT_NAME)) + major = importExportedName(minor, nameBuffer, name); + else + major = GSS_S_BAD_NAMETYPE; + + if (GSS_ERROR(major)) + gssEapReleaseName(&tmpMinor, name); + + return major; +} + OM_uint32 gssEapExportName(OM_uint32 *minor, const gss_name_t name, gss_buffer_t exportedName, @@ -156,13 +348,13 @@ OM_uint32 gssEapExportName(OM_uint32 *minor, } krbNameLen = strlen(krbName); - exportedName->length = 6 + GSS_EAP_MECHANISM->length + krbNameLen; + exportedName->length = 6 + GSS_EAP_MECHANISM->length + 4 + krbNameLen; if (composite) { /* TODO: export SAML/AVP, this is pending specification */ GSSEAP_NOT_IMPLEMENTED; } - exportedName->value = GSSEAP_MALLOC(exportedName->value); + exportedName->value = GSSEAP_MALLOC(exportedName->length); if (exportedName->value == NULL) { *minor = ENOMEM; major = GSS_S_FAILURE;