From: Luke Howard Date: Wed, 16 Mar 2011 04:18:32 +0000 (+1100) Subject: Fix for OpenSSH interoperability X-Git-Tag: dvd/201105~12^2~106 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mech_eap.orig;a=commitdiff_plain;h=2ef09e13ed37e4ee3e333734e4c3a7ec2cb10d76 Fix for OpenSSH interoperability OpenSSH requires the exported name token to include the actual OID of the selected mechanism. We were using an OID that identified a family of GSS EAP mechanisms. We now use the concrete OID where possible. Conflicts: mech_eap/util_name.c --- diff --git a/accept_sec_context.c b/accept_sec_context.c index 5829ed9..9ef0fc9 100644 --- a/accept_sec_context.c +++ b/accept_sec_context.c @@ -82,6 +82,7 @@ acceptReadyEap(OM_uint32 *minor, gss_ctx_id_t ctx, gss_cred_id_t cred) major = gssEapImportName(minor, &nameBuf, (ctx->gssFlags & GSS_C_ANON_FLAG) ? GSS_C_NT_ANONYMOUS : GSS_C_NT_USER_NAME, + ctx->mechanismUsed, &ctx->initiatorName); if (GSS_ERROR(major)) return major; @@ -272,7 +273,7 @@ importInitiatorIdentity(OM_uint32 *minor, gssEapReleaseName(&tmpMinor, &ctx->initiatorName); return gssEapImportName(minor, &nameBuf, GSS_C_NT_USER_NAME, - &ctx->initiatorName); + ctx->mechanismUsed, &ctx->initiatorName); } /* diff --git a/gssapiP_eap.h b/gssapiP_eap.h index 10cd176..0f12811 100644 --- a/gssapiP_eap.h +++ b/gssapiP_eap.h @@ -105,6 +105,7 @@ struct gss_name_struct { GSSEAP_MUTEX mutex; /* mutex protects attrCtx */ OM_uint32 flags; + gss_OID mechanismUsed; /* this is immutable */ krb5_principal krbPrincipal; /* this is immutable */ struct gss_eap_attr_ctx *attrCtx; }; diff --git a/import_name.c b/import_name.c index d20d75c..87f0830 100644 --- a/import_name.c +++ b/import_name.c @@ -43,5 +43,5 @@ gss_import_name(OM_uint32 *minor, gss_name_t *output_name) { return gssEapImportName(minor, import_name_buffer, - input_name_type, output_name); + input_name_type, GSS_C_NO_OID, output_name); } diff --git a/init_sec_context.c b/init_sec_context.c index 1f445bc..c42fa88 100644 --- a/init_sec_context.c +++ b/init_sec_context.c @@ -543,7 +543,9 @@ eapGssSmInitAcceptorName(OM_uint32 *minor, ctx->acceptorName == GSS_C_NO_NAME) { /* Accept target name hint from acceptor */ major = gssEapImportName(minor, inputToken, - GSS_C_NT_USER_NAME, &ctx->acceptorName); + GSS_C_NT_USER_NAME, + ctx->mechanismUsed, + &ctx->acceptorName); if (GSS_ERROR(major)) return major; } diff --git a/util.h b/util.h index ddf95a9..8756c95 100644 --- a/util.h +++ b/util.h @@ -467,6 +467,7 @@ OM_uint32 gssEapExportNameInternal(OM_uint32 *minor, OM_uint32 gssEapImportName(OM_uint32 *minor, const gss_buffer_t input_name_buffer, gss_OID input_name_type, + gss_OID input_mech_type, gss_name_t *output_name); OM_uint32 gssEapImportNameInternal(OM_uint32 *minor, const gss_buffer_t input_name_buffer, diff --git a/util_cred.c b/util_cred.c index 64b9284..a2a01ba 100644 --- a/util_cred.c +++ b/util_cred.c @@ -184,7 +184,13 @@ gssEapAcquireCred(OM_uint32 *minor, } if (nameBuf.length != 0) { - major = gssEapImportName(minor, &nameBuf, nameType, &cred->name); + gss_OID mech = GSS_C_NO_OID; + + if (cred->mechanisms != GSS_C_NO_OID_SET && + cred->mechanisms->count == 1) + mech = &cred->mechanisms->elements[0]; + + major = gssEapImportName(minor, &nameBuf, nameType, mech, &cred->name); if (GSS_ERROR(major)) goto cleanup; } diff --git a/util_name.c b/util_name.c index 70d23e2..dad8fb9 100644 --- a/util_name.c +++ b/util_name.c @@ -111,6 +111,7 @@ gssEapReleaseName(OM_uint32 *minor, gss_name_t *pName) GSSEAP_KRB_INIT(&krbContext); krb5_free_principal(krbContext, name->krbPrincipal); + gssEapReleaseOid(&tmpMinor, &name->mechanismUsed); gssEapReleaseAttrContext(&tmpMinor, name); @@ -282,7 +283,10 @@ gssEapImportNameInternal(OM_uint32 *minor, remain = nameBuffer->length; if (flags & EXPORT_NAME_FLAG_OID) { - if (remain < 6 + GSS_EAP_MECHANISM->length) + gss_OID_desc mech; + + /* TOK_ID || MECH_OID_LEN || MECH_OID */ + if (remain < 6) return GSS_S_BAD_NAME; if (flags & EXPORT_NAME_FLAG_COMPOSITE) @@ -297,18 +301,34 @@ gssEapImportNameInternal(OM_uint32 *minor, /* MECH_OID_LEN */ len = load_uint16_be(p); - if (len != 2 + GSS_EAP_MECHANISM->length) + if (len < 2) return GSS_S_BAD_NAME; UPDATE_REMAIN(2); /* MECH_OID */ if (p[0] != 0x06) return GSS_S_BAD_NAME; - if (p[1] != GSS_EAP_MECHANISM->length) - return GSS_S_BAD_MECH; - if (memcmp(&p[2], GSS_EAP_MECHANISM->elements, GSS_EAP_MECHANISM->length)) - return GSS_S_BAD_MECH; - UPDATE_REMAIN(2 + GSS_EAP_MECHANISM->length); + + mech.length = p[1]; + mech.elements = &p[2]; + + CHECK_REMAIN(mech.length); + + if (!gssEapIsMechanismOid(&mech)) { + major = GSS_S_BAD_NAME; + *minor = GSSEAP_WRONG_MECH; + goto cleanup; + } + + if (oidEqual(&mech, GSS_EAP_MECHANISM)) { + name->mechanismUsed = GSS_C_NO_OID; + } else if (!gssEapInternalizeOid(&mech, &name->mechanismUsed)) { + major = duplicateOid(minor, &mech, &name->mechanismUsed); + if (GSS_ERROR(major)) + goto cleanup; + } + + UPDATE_REMAIN(2 + mech.length); } /* NAME_LEN */ @@ -379,7 +399,8 @@ OM_uint32 gssEapImportName(OM_uint32 *minor, const gss_buffer_t nameBuffer, gss_OID nameType, - gss_name_t *name) + gss_OID mechType, + gss_name_t *pName) { struct gss_eap_name_import_provider nameTypes[] = { { GSS_C_NT_USER_NAME, importUserName }, @@ -393,18 +414,36 @@ gssEapImportName(OM_uint32 *minor, #endif }; size_t i; - - *name = GSS_C_NO_NAME; + OM_uint32 major = GSS_S_BAD_NAMETYPE; + OM_uint32 tmpMinor; + gss_name_t name = GSS_C_NO_NAME; if (nameType == GSS_C_NO_OID) nameType = nameTypes[0].oid; for (i = 0; i < sizeof(nameTypes) / sizeof(nameTypes[0]); i++) { - if (oidEqual(nameTypes[i].oid, nameType)) - return nameTypes[i].import(minor, nameBuffer, name); + if (oidEqual(nameTypes[i].oid, nameType)) { + major = nameTypes[i].import(minor, nameBuffer, &name); + break; + } } - return GSS_S_BAD_NAMETYPE; + if (major == GSS_S_COMPLETE && + mechType != GSS_C_NO_OID) { + assert(gssEapIsConcreteMechanismOid(mechType)); + assert(name->mechanismUsed == GSS_C_NO_OID); + + if (!gssEapInternalizeOid(mechType, &name->mechanismUsed)) { + major = duplicateOid(minor, mechType, &name->mechanismUsed); + } + } + + if (GSS_ERROR(major)) + gssEapReleaseName(&tmpMinor, &name); + else + *pName = name; + + return major; } OM_uint32 @@ -428,10 +467,16 @@ gssEapExportNameInternal(OM_uint32 *minor, size_t krbNameLen, exportedNameLen; unsigned char *p; gss_buffer_desc attrs = GSS_C_EMPTY_BUFFER; + gss_OID mech; exportedName->length = 0; exportedName->value = NULL; + if (name->mechanismUsed != GSS_C_NO_OID) + mech = name->mechanismUsed; + else + mech = GSS_EAP_MECHANISM; + GSSEAP_KRB_INIT(&krbContext); *minor = krb5_unparse_name(krbContext, name->krbPrincipal, &krbName); @@ -443,7 +488,7 @@ gssEapExportNameInternal(OM_uint32 *minor, exportedNameLen = 0; if (flags & EXPORT_NAME_FLAG_OID) { - exportedNameLen += 6 + GSS_EAP_MECHANISM->length; + exportedNameLen += 6 + mech->length; } exportedNameLen += 4 + krbNameLen; if (flags & EXPORT_NAME_FLAG_COMPOSITE) { @@ -470,14 +515,14 @@ gssEapExportNameInternal(OM_uint32 *minor, : TOK_TYPE_EXPORT_NAME, p); p += 2; - store_uint16_be(GSS_EAP_MECHANISM->length + 2, p); + store_uint16_be(mech->length + 2, p); p += 2; /* MECH_OID */ *p++ = 0x06; - *p++ = GSS_EAP_MECHANISM->length & 0xff; - memcpy(p, GSS_EAP_MECHANISM->elements, GSS_EAP_MECHANISM->length); - p += GSS_EAP_MECHANISM->length; + *p++ = mech->length & 0xff; + memcpy(p, mech->elements, mech->length); + p += mech->length; } /* NAME_LEN */ @@ -528,6 +573,22 @@ gssEapDuplicateName(OM_uint32 *minor, return major; } + if (input_name->mechanismUsed == GSS_C_NO_OID) { + name->mechanismUsed = GSS_C_NO_OID; + } else if (gssEapIsConcreteMechanismOid(input_name->mechanismUsed)) { + if (!gssEapInternalizeOid(input_name->mechanismUsed, + &name->mechanismUsed)) { + major = duplicateOid(minor, input_name->mechanismUsed, + &name->mechanismUsed); + if (GSS_ERROR(major)) + goto cleanup; + } + } else { + major = GSS_S_BAD_MECH; + *minor = GSSEAP_WRONG_MECH; + goto cleanup; + } + name->flags = input_name->flags; *minor = krb5_copy_principal(krbContext, input_name->krbPrincipal, diff --git a/util_reauth.c b/util_reauth.c index f1112ca..22f089f 100644 --- a/util_reauth.c +++ b/util_reauth.c @@ -735,7 +735,7 @@ gssEapGlueToMechName(OM_uint32 *minor, goto cleanup; major = gssEapImportName(minor, &nameBuf, GSS_C_NT_USER_NAME, - pMechName); + ctx->mechanismUsed, pMechName); if (GSS_ERROR(major)) goto cleanup;