X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=util_name.c;h=b1475f86bd238a4a974f84f7a665d8d5f7d871a1;hb=163856b1a70d7773c46d4ea5495b85c4dce0f089;hp=50ff1ec86187080f4ab60e6e7dd5e2471626a798;hpb=0f049c2d14f54631ff88c12edb005f89b372d65a;p=mech_eap.git diff --git a/util_name.c b/util_name.c index 50ff1ec..b1475f8 100644 --- a/util_name.c +++ b/util_name.c @@ -53,11 +53,15 @@ * or implied warranty. */ +/* + * Name utility routines. + */ + #include "gssapiP_eap.h" static gss_OID_desc gssEapNtPrincipalName = { - /* 1.3.6.1.4.1.5322.21.2.1 */ - 10, "\x2B\x06\x01\x04\x01\xA9\x4A\x15\x02\x01" + /* 1.3.6.1.4.1.5322.22.2.1 */ + 10, "\x2B\x06\x01\x04\x01\xA9\x4A\x16\x02\x01" }; gss_OID GSS_EAP_NT_PRINCIPAL_NAME = &gssEapNtPrincipalName; @@ -94,6 +98,8 @@ gssEapReleaseName(OM_uint32 *minor, gss_name_t *pName) krb5_context krbContext = NULL; OM_uint32 tmpMinor; + *minor = 0; + if (pName == NULL) { return GSS_S_COMPLETE; } @@ -112,7 +118,6 @@ gssEapReleaseName(OM_uint32 *minor, gss_name_t *pName) GSSEAP_FREE(name); *pName = NULL; - *minor = 0; return GSS_S_COMPLETE; } @@ -131,10 +136,10 @@ krbPrincipalToName(OM_uint32 *minor, name->krbPrincipal = *principal; *principal = NULL; - if (name->krbPrincipal->length == 1) { - name->flags |= NAME_FLAG_NAI; - } else { + if (KRB_PRINC_LENGTH(name->krbPrincipal) > 1) { name->flags |= NAME_FLAG_SERVICE; + } else { + name->flags |= NAME_FLAG_NAI; } *pName = name; @@ -163,13 +168,13 @@ importServiceName(OM_uint32 *minor, 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) { + if (krb5_sname_to_principal(krbContext, host, service, + KRB5_NT_SRV_HST, &krbPrinc) != 0) { GSSEAP_FREE(service); + *minor = GSSEAP_BAD_SERVICE_NAME; return GSS_S_FAILURE; } @@ -194,14 +199,21 @@ importUserName(OM_uint32 *minor, GSSEAP_KRB_INIT(&krbContext); - major = bufferToString(minor, nameBuffer, &nameString); - if (GSS_ERROR(major)) - return major; + if (nameBuffer == GSS_C_NO_BUFFER) { + *minor = krb5_copy_principal(krbContext, + krbAnonymousPrincipal(), &krbPrinc); + if (*minor != 0) + return GSS_S_FAILURE; + } else { + 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; + *minor = krb5_parse_name(krbContext, nameString, &krbPrinc); + if (*minor != 0) { + GSSEAP_FREE(nameString); + return GSS_S_FAILURE; + } } major = krbPrincipalToName(minor, &krbPrinc, pName); @@ -213,6 +225,30 @@ importUserName(OM_uint32 *minor, return major; } +static OM_uint32 +importAnonymousName(OM_uint32 *minor, + const gss_buffer_t nameBuffer, + gss_name_t *pName) +{ + OM_uint32 major; + krb5_context krbContext; + krb5_principal krbPrinc; + + GSSEAP_KRB_INIT(&krbContext); + + *minor = krb5_copy_principal(krbContext, krbAnonymousPrincipal(), + &krbPrinc); + if (*minor != 0) + return GSS_S_FAILURE; + + major = krbPrincipalToName(minor, &krbPrinc, pName); + if (GSS_ERROR(major)) { + krb5_free_principal(krbContext, krbPrinc); + } + + return major; +} + #define UPDATE_REMAIN(n) do { \ p += (n); \ remain -= (n); \ @@ -220,8 +256,8 @@ importUserName(OM_uint32 *minor, #define CHECK_REMAIN(n) do { \ if (remain < (n)) { \ - *minor = ERANGE; \ major = GSS_S_BAD_NAME; \ + *minor = GSSEAP_TOK_TRUNC; \ goto cleanup; \ } \ } while (0) @@ -292,13 +328,8 @@ gssEapImportNameInternal(OM_uint32 *minor, if (flags & EXPORT_NAME_FLAG_COMPOSITE) { gss_buffer_desc buf; - CHECK_REMAIN(4); - buf.length = load_uint32_be(p); - UPDATE_REMAIN(4); - - CHECK_REMAIN(buf.length); + buf.length = remain; buf.value = p; - UPDATE_REMAIN(buf.length); major = gssEapImportAttrContext(minor, &buf, name); if (GSS_ERROR(major)) @@ -306,6 +337,7 @@ gssEapImportNameInternal(OM_uint32 *minor, } major = GSS_S_COMPLETE; + *minor = 0; cleanup: if (GSS_ERROR(major)) @@ -316,39 +348,62 @@ cleanup: return major; } +static OM_uint32 +importExportName(OM_uint32 *minor, + const gss_buffer_t nameBuffer, + gss_name_t *name) +{ + return gssEapImportNameInternal(minor, nameBuffer, name, + EXPORT_NAME_FLAG_OID); +} + +#ifdef HAVE_GSS_C_NT_COMPOSITE_EXPORT +static OM_uint32 +importCompositeExportName(OM_uint32 *minor, + const gss_buffer_t nameBuffer, + gss_name_t *name) +{ + return gssEapImportNameInternal(minor, nameBuffer, name, + EXPORT_NAME_FLAG_OID | + EXPORT_NAME_FLAG_COMPOSITE); +} +#endif + +struct gss_eap_name_import_provider { + gss_OID oid; + OM_uint32 (*import)(OM_uint32 *, const gss_buffer_t, gss_name_t *); +}; + OM_uint32 gssEapImportName(OM_uint32 *minor, const gss_buffer_t nameBuffer, gss_OID nameType, gss_name_t *name) { - OM_uint32 major, tmpMinor; + struct gss_eap_name_import_provider nameTypes[] = { + { GSS_C_NT_USER_NAME, importUserName }, + { GSS_EAP_NT_PRINCIPAL_NAME, importUserName }, + { GSS_C_NT_HOSTBASED_SERVICE, importServiceName }, + { GSS_C_NT_HOSTBASED_SERVICE_X, importServiceName }, + { GSS_C_NT_ANONYMOUS, importAnonymousName }, + { GSS_C_NT_EXPORT_NAME, importExportName }, +#ifdef HAVE_GSS_C_NT_COMPOSITE_EXPORT + { GSS_C_NT_COMPOSITE_EXPORT, importCompositeExportName }, +#endif + }; + size_t i; *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 = gssEapImportNameInternal(minor, nameBuffer, name, - EXPORT_NAME_FLAG_OID); -#ifdef HAVE_GSS_C_NT_COMPOSITE_EXPORT - else if (oidEqual(nameType, GSS_C_NT_COMPOSITE_EXPORT)) - major = gssEapImportNameInternal(minor, nameBuffer, name, - EXPORT_NAME_FLAG_OID | - EXPORT_NAME_FLAG_COMPOSITE); -#endif - else - major = GSS_S_BAD_NAMETYPE; + if (nameType == GSS_C_NO_OID) + nameType = nameTypes[0].oid; - if (GSS_ERROR(major)) - gssEapReleaseName(&tmpMinor, name); + for (i = 0; i < sizeof(nameTypes) / sizeof(nameTypes[0]); i++) { + if (oidEqual(nameTypes[i].oid, nameType)) + return nameTypes[i].import(minor, nameBuffer, name); + } - return major; + return GSS_S_BAD_NAMETYPE; } OM_uint32 @@ -377,7 +432,6 @@ gssEapExportNameInternal(OM_uint32 *minor, exportedName->value = NULL; GSSEAP_KRB_INIT(&krbContext); - GSSEAP_MUTEX_LOCK(&name->mutex); *minor = krb5_unparse_name(krbContext, name->krbPrincipal, &krbName); if (*minor != 0) { @@ -395,7 +449,7 @@ gssEapExportNameInternal(OM_uint32 *minor, major = gssEapExportAttrContext(minor, name, &attrs); if (GSS_ERROR(major)) goto cleanup; - exportedNameLen += 4 + attrs.length; + exportedNameLen += attrs.length; } exportedName->value = GSSEAP_MALLOC(exportedNameLen); @@ -434,16 +488,16 @@ gssEapExportNameInternal(OM_uint32 *minor, p += krbNameLen; if (flags & EXPORT_NAME_FLAG_COMPOSITE) { - store_uint32_be(attrs.length, p); - memcpy(&p[4], attrs.value, attrs.length); - p += 4 + attrs.length; + memcpy(p, attrs.value, attrs.length); + p += attrs.length; } - *minor = 0; + assert(p == (unsigned char *)exportedName->value + exportedNameLen); + major = GSS_S_COMPLETE; + *minor = 0; cleanup: - GSSEAP_MUTEX_UNLOCK(&name->mutex); gss_release_buffer(&tmpMinor, &attrs); if (GSS_ERROR(major)) gss_release_buffer(&tmpMinor, exportedName); @@ -451,3 +505,97 @@ cleanup: return major; } + +OM_uint32 +gssEapDuplicateName(OM_uint32 *minor, + const gss_name_t input_name, + gss_name_t *dest_name) +{ + OM_uint32 major, tmpMinor; + krb5_context krbContext; + gss_name_t name; + + if (input_name == GSS_C_NO_NAME) { + *minor = EINVAL; + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME; + } + + GSSEAP_KRB_INIT(&krbContext); + + major = gssEapAllocName(minor, &name); + if (GSS_ERROR(major)) { + return major; + } + + name->flags = input_name->flags; + + *minor = krb5_copy_principal(krbContext, input_name->krbPrincipal, + &name->krbPrincipal); + if (*minor != 0) { + major = GSS_S_FAILURE; + goto cleanup; + } + + if (input_name->attrCtx != NULL) { + major = gssEapDuplicateAttrContext(minor, input_name, name); + if (GSS_ERROR(major)) + goto cleanup; + } + + *dest_name = name; + +cleanup: + if (GSS_ERROR(major)) { + gssEapReleaseName(&tmpMinor, &name); + } + + return major; +} + +OM_uint32 +gssEapDisplayName(OM_uint32 *minor, + gss_name_t name, + gss_buffer_t output_name_buffer, + gss_OID *output_name_type) +{ + OM_uint32 major; + krb5_context krbContext; + char *krbName; + gss_OID name_type; + + GSSEAP_KRB_INIT(&krbContext); + + output_name_buffer->length = 0; + output_name_buffer->value = NULL; + + if (name == GSS_C_NO_NAME) { + *minor = EINVAL; + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME; + } + + *minor = krb5_unparse_name(krbContext, name->krbPrincipal, &krbName); + if (*minor != 0) { + return GSS_S_FAILURE; + } + + major = makeStringBuffer(minor, krbName, output_name_buffer); + if (GSS_ERROR(major)) { + krb5_free_unparsed_name(krbContext, krbName); + return major; + } + + krb5_free_unparsed_name(krbContext, krbName); + + if (KRB_PRINC_TYPE(name->krbPrincipal) == KRB5_NT_WELLKNOWN && + krb5_principal_compare(krbContext, + name->krbPrincipal, krbAnonymousPrincipal())) { + name_type = GSS_C_NT_ANONYMOUS; + } else { + name_type = GSS_EAP_NT_PRINCIPAL_NAME; + } + + if (output_name_type != NULL) + *output_name_type = name_type; + + return GSS_S_COMPLETE; +}