X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=util_name.c;h=aa19b943c7514306adf6bdea9359c0a6c19838cc;hb=refs%2Fheads%2Fjson-name;hp=4add1fea9dcb909228bf258507c2b72af5a0d463;hpb=2578cdaa1d058cb74644cb9a0ddee990221abd74;p=mech_eap.orig diff --git a/util_name.c b/util_name.c index 4add1fe..aa19b94 100644 --- a/util_name.c +++ b/util_name.c @@ -149,15 +149,15 @@ krbPrincipalToName(OM_uint32 *minor, return GSS_S_COMPLETE; } -static krb5_error_code -gssEapGetDefaultRealm(krb5_context krbContext, char **defaultRealm) +static char * +gssEapGetDefaultRealm(krb5_context krbContext) { - *defaultRealm = NULL; + char *defaultRealm = NULL; krb5_appdefault_string(krbContext, "eap_gss", - NULL, "default_realm", "", defaultRealm); + NULL, "default_realm", "", &defaultRealm); - return (*defaultRealm != NULL) ? 0 : KRB5_CONFIG_NODEFREALM; + return defaultRealm; } static OM_uint32 @@ -183,7 +183,7 @@ importServiceName(OM_uint32 *minor, host++; } - gssEapGetDefaultRealm(krbContext, &realm); + realm = gssEapGetDefaultRealm(krbContext); code = krb5_build_principal(krbContext, &krbPrinc, @@ -211,10 +211,16 @@ importServiceName(OM_uint32 *minor, return major; } +#define IMPORT_FLAG_DEFAULT_REALM 0x1 + +/* + * Import an EAP name, possibly appending the default GSS EAP realm, + */ static OM_uint32 -importUserName(OM_uint32 *minor, - const gss_buffer_t nameBuffer, - gss_name_t *pName) +importEapNameFlags(OM_uint32 *minor, + const gss_buffer_t nameBuffer, + OM_uint32 importFlags, + gss_name_t *pName) { OM_uint32 major; krb5_context krbContext; @@ -239,27 +245,33 @@ importUserName(OM_uint32 *minor, /* * First, attempt to parse the name on the assumption that it includes - * a qualifying realm. + * a qualifying realm. This allows us to avoid accidentally appending + * the default Kerberos realm to an unqualified name. (A bug in MIT + * Kerberos prevents the default realm being set to an empty value.) */ code = krb5_parse_name_flags(krbContext, nameString, KRB5_PRINCIPAL_PARSE_REQUIRE_REALM, &krbPrinc); if (code == KRB5_PARSE_MALFORMED) { char *defaultRealm = NULL; - int flags = 0; + int parseFlags = 0; - /* - * We need an explicit appdefaults check because, at least with MIT - * Kerberos, setting the context realm to NULL will reset it to the - * default Kerberos realm after the second call to get_default_realm. - * We want to make sure that the default Kerberos realm does not end - * up accidentally appended to an unqualified name. - */ - gssEapGetDefaultRealm(krbContext, &defaultRealm); + /* Possibly append the default EAP realm if required */ + if (importFlags & IMPORT_FLAG_DEFAULT_REALM) + defaultRealm = gssEapGetDefaultRealm(krbContext); + /* If no default realm, leave the realm empty in the parsed name */ if (defaultRealm == NULL || defaultRealm[0] == '\0') - flags |= KRB5_PRINCIPAL_PARSE_NO_REALM; + parseFlags |= KRB5_PRINCIPAL_PARSE_NO_REALM; - code = krb5_parse_name_flags(krbContext, nameString, flags, &krbPrinc); + code = krb5_parse_name_flags(krbContext, nameString, parseFlags, &krbPrinc); + +#ifdef HAVE_HEIMDAL_VERSION + if (code == 0 && KRB_PRINC_REALM(krbPrinc) == NULL) { + KRB_PRINC_REALM(krbPrinc) = GSSEAP_CALLOC(1, sizeof(char)); + if (KRB_PRINC_REALM(krbPrinc) == NULL) + code = ENOMEM; + } +#endif if (defaultRealm != NULL) GSSEAP_FREE(defaultRealm); @@ -283,27 +295,27 @@ importUserName(OM_uint32 *minor, } static OM_uint32 +importEapName(OM_uint32 *minor, + const gss_buffer_t nameBuffer, + gss_name_t *pName) +{ + return importEapNameFlags(minor, nameBuffer, 0, pName); +} + +static OM_uint32 +importUserName(OM_uint32 *minor, + const gss_buffer_t nameBuffer, + gss_name_t *pName) +{ + return importEapNameFlags(minor, nameBuffer, IMPORT_FLAG_DEFAULT_REALM, pName); +} + +static OM_uint32 importAnonymousName(OM_uint32 *minor, const gss_buffer_t nameBuffer GSSEAP_UNUSED, 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; + return importEapNameFlags(minor, GSS_C_NO_BUFFER, 0, pName); } #define UPDATE_REMAIN(n) do { \ @@ -393,7 +405,7 @@ gssEapImportNameInternal(OM_uint32 *minor, buf.value = p; UPDATE_REMAIN(len); - major = importUserName(minor, &buf, &name); + major = importEapNameFlags(minor, &buf, 0, &name); if (GSS_ERROR(major)) goto cleanup; @@ -459,7 +471,7 @@ gssEapImportName(OM_uint32 *minor, gss_name_t *pName) { struct gss_eap_name_import_provider nameTypes[] = { - { GSS_EAP_NT_EAP_NAME, importUserName }, + { GSS_EAP_NT_EAP_NAME, importEapName }, { GSS_C_NT_USER_NAME, importUserName }, { GSS_C_NT_HOSTBASED_SERVICE, importServiceName }, { GSS_C_NT_HOSTBASED_SERVICE_X, importServiceName }, @@ -515,9 +527,8 @@ gssEapExportNameInternal(OM_uint32 *minor, unsigned int flags) { OM_uint32 major = GSS_S_FAILURE, tmpMinor; - krb5_context krbContext; - char *krbName = NULL; - size_t krbNameLen, exportedNameLen; + gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER; + size_t exportedNameLen; unsigned char *p; gss_buffer_desc attrs = GSS_C_EMPTY_BUFFER; gss_OID mech; @@ -530,20 +541,15 @@ gssEapExportNameInternal(OM_uint32 *minor, else mech = GSS_EAP_MECHANISM; - GSSEAP_KRB_INIT(&krbContext); - - *minor = krb5_unparse_name(krbContext, name->krbPrincipal, &krbName); - if (*minor != 0) { - major = GSS_S_FAILURE; + major = gssEapDisplayName(minor, name, &nameBuf, NULL); + if (GSS_ERROR(major)) goto cleanup; - } - krbNameLen = strlen(krbName); exportedNameLen = 0; if (flags & EXPORT_NAME_FLAG_OID) { exportedNameLen += 6 + mech->length; } - exportedNameLen += 4 + krbNameLen; + exportedNameLen += 4 + nameBuf.length; if (flags & EXPORT_NAME_FLAG_COMPOSITE) { major = gssEapExportAttrContext(minor, name, &attrs); if (GSS_ERROR(major)) @@ -579,12 +585,12 @@ gssEapExportNameInternal(OM_uint32 *minor, } /* NAME_LEN */ - store_uint32_be(krbNameLen, p); + store_uint32_be(nameBuf.length, p); p += 4; /* NAME */ - memcpy(p, krbName, krbNameLen); - p += krbNameLen; + memcpy(p, nameBuf.value, nameBuf.length); + p += nameBuf.length; if (flags & EXPORT_NAME_FLAG_COMPOSITE) { memcpy(p, attrs.value, attrs.length); @@ -598,9 +604,9 @@ gssEapExportNameInternal(OM_uint32 *minor, cleanup: gss_release_buffer(&tmpMinor, &attrs); + gss_release_buffer(&tmpMinor, &nameBuf); if (GSS_ERROR(major)) gss_release_buffer(&tmpMinor, exportedName); - krb5_free_unparsed_name(krbContext, krbName); return major; } @@ -684,6 +690,7 @@ gssEapDisplayName(OM_uint32 *minor, krb5_context krbContext; char *krbName; gss_OID name_type; + int flags = 0; GSSEAP_KRB_INIT(&krbContext); @@ -695,7 +702,20 @@ gssEapDisplayName(OM_uint32 *minor, return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME; } - *minor = krb5_unparse_name(krbContext, name->krbPrincipal, &krbName); + /* + * According to draft-ietf-abfab-gss-eap-01, when the realm is + * absent the trailing '@' is not included. + */ +#ifdef HAVE_HEIMDAL_VERSION + if (KRB_PRINC_REALM(name->krbPrincipal) == NULL || + KRB_PRINC_REALM(name->krbPrincipal)[0] == '\0') +#else + if (KRB_PRINC_REALM(name->krbPrincipal)->length == 0) +#endif + flags |= KRB5_PRINCIPAL_UNPARSE_NO_REALM; + + *minor = krb5_unparse_name_flags(krbContext, name->krbPrincipal, + flags, &krbName); if (*minor != 0) { return GSS_S_FAILURE; } @@ -721,3 +741,27 @@ gssEapDisplayName(OM_uint32 *minor, return GSS_S_COMPLETE; } + +OM_uint32 +gssEapCompareName(OM_uint32 *minor, + gss_name_t name1, + gss_name_t name2, + int *name_equal) +{ + krb5_context krbContext; + + *minor = 0; + + if (name1 == GSS_C_NO_NAME && name2 == GSS_C_NO_NAME) { + *name_equal = 1; + } else if (name1 != GSS_C_NO_NAME && name2 != GSS_C_NO_NAME) { + GSSEAP_KRB_INIT(&krbContext); + + /* krbPrincipal is immutable, so lock not required */ + *name_equal = krb5_principal_compare(krbContext, + name1->krbPrincipal, + name2->krbPrincipal); + } + + return GSS_S_COMPLETE; +}