X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=accept_sec_context.c;h=981a7d8b3d29a36a69e6a110d83768a5e37b4f7d;hb=6fd9f5a521f9efa7cb9dd43f90ae8f33c83c66e1;hp=42c29c2e0b609e91e4173abe4421fcadfbb227b2;hpb=849faf84b633a519a29c54f182a4ac643425b760;p=mech_eap.git diff --git a/accept_sec_context.c b/accept_sec_context.c index 42c29c2..981a7d8 100644 --- a/accept_sec_context.c +++ b/accept_sec_context.c @@ -38,7 +38,7 @@ static OM_uint32 acceptReady(OM_uint32 *minor, gss_ctx_id_t ctx, gss_cred_id_t cred) { - OM_uint32 major; + OM_uint32 major, tmpMinor; VALUE_PAIR *vp; gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER; @@ -48,26 +48,26 @@ acceptReady(OM_uint32 *minor, gss_ctx_id_t ctx, gss_cred_id_t cred) if (GSS_ERROR(major)) return major; + gssEapReleaseName(&tmpMinor, &ctx->initiatorName); + vp = rc_avpair_get(ctx->acceptorCtx.avps, PW_USER_NAME, 0); if (vp != NULL) { nameBuf.length = vp->lvalue; nameBuf.value = vp->strvalue; - } else if (ctx->initiatorName == GSS_C_NO_NAME) { + } else { ctx->gssFlags |= GSS_C_ANON_FLAG; } - if (nameBuf.length != 0 || ctx->initiatorName == GSS_C_NO_NAME) { - major = gssEapImportName(minor, &nameBuf, GSS_C_NT_USER_NAME, - &ctx->initiatorName); - if (GSS_ERROR(major)) - return major; - } + major = gssEapImportName(minor, &nameBuf, GSS_C_NT_USER_NAME, + &ctx->initiatorName); + if (GSS_ERROR(major)) + return major; ctx->initiatorName->attrCtx = gssEapCreateAttrContext(cred, ctx); vp = rc_avpair_get(ctx->acceptorCtx.avps, - RADIUS_VENDOR_ATTR_MS_MPPE_SEND_KEY, - RADIUS_VENDOR_ID_MICROSOFT); + VENDOR_ATTR_MS_MPPE_SEND_KEY, + VENDOR_ID_MICROSOFT); if (ctx->encryptionType != ENCTYPE_NULL && vp != NULL) { major = gssEapDeriveRfc3961Key(minor, (unsigned char *)vp->strvalue, @@ -126,10 +126,10 @@ eapGssSmAcceptIdentity(OM_uint32 *minor, if (GSS_ERROR(major)) return major; - if (ctx->acceptorName == GSS_C_NO_NAME && - cred != GSS_C_NO_CREDENTIAL && - cred->name != GSS_C_NO_NAME) { - major = gss_duplicate_name(minor, cred->name, &ctx->acceptorName); + assert(ctx->acceptorName == GSS_C_NO_NAME); + + if (cred != GSS_C_NO_CREDENTIAL && cred->name != GSS_C_NO_NAME) { + major = gssEapDuplicateName(minor, cred->name, &ctx->acceptorName); if (GSS_ERROR(major)) return major; } @@ -152,28 +152,85 @@ eapGssSmAcceptIdentity(OM_uint32 *minor, } static OM_uint32 -importInitiatorIdentity(OM_uint32 *minor, - gss_ctx_id_t ctx, - gss_buffer_t inputToken, - gss_buffer_t nameBuf) +setAcceptorIdentity(OM_uint32 *minor, + gss_ctx_id_t ctx, + VALUE_PAIR **avps) { - OM_uint32 major, tmpMinor; - struct eap_hdr *pdu = (struct eap_hdr *)inputToken->value; - unsigned char *pos = (unsigned char *)(pdu + 1); - gss_name_t name; + OM_uint32 major; + gss_buffer_desc nameBuf; + krb5_context krbContext = NULL; + krb5_principal krbPrinc; + + /* Awaits further specification */ + if (ctx->acceptorName == GSS_C_NO_NAME) + return GSS_S_COMPLETE; + + GSSEAP_KRB_INIT(&krbContext); + + krbPrinc = ctx->acceptorName->krbPrincipal; + assert(krbPrinc != NULL); - assert(pdu->code == EAP_CODE_RESPONSE); - assert(pos[0] == EAP_TYPE_IDENTITY); + if (krb5_princ_size(krbContext, krbPrinc) < 2) + return GSS_S_BAD_NAME; - nameBuf->value = pos + 1; - nameBuf->length = inputToken->length - sizeof(*pdu) - 1; + /* Acceptor-Service-Name */ + krbDataToGssBuffer(krb5_princ_component(krbContext, krbPrinc, 0), &nameBuf); - major = gssEapImportName(minor, nameBuf, GSS_C_NT_USER_NAME, &name); + major = addAvpFromBuffer(minor, ctx->acceptorCtx.radHandle, avps, + VENDOR_ATTR_GSS_ACCEPTOR_SERVICE_NAME, + VENDOR_ID_UKERNA, + &nameBuf); if (GSS_ERROR(major)) return major; - gssEapReleaseName(&tmpMinor, &ctx->initiatorName); - ctx->initiatorName = name; + /* Acceptor-Host-Name */ + krbDataToGssBuffer(krb5_princ_component(krbContext, krbPrinc, 1), &nameBuf); + + major = addAvpFromBuffer(minor, ctx->acceptorCtx.radHandle, avps, + VENDOR_ATTR_GSS_ACCEPTOR_HOST_NAME, + VENDOR_ID_UKERNA, + &nameBuf); + if (GSS_ERROR(major)) + return major; + + if (krb5_princ_size(krbContext, krbPrinc) > 2) { + /* Acceptor-Service-Specific */ + krb5_principal_data ssiPrinc = *krbPrinc; + char *ssi; + + krb5_princ_size(krbContext, &ssiPrinc) -= 2; + krb5_princ_name(krbContext, &ssiPrinc) += 2; + + *minor = krb5_unparse_name_flags(krbContext, &ssiPrinc, + KRB5_PRINCIPAL_UNPARSE_NO_REALM, &ssi); + if (*minor != 0) + return GSS_S_FAILURE; + + nameBuf.value = ssi; + nameBuf.length = strlen(ssi); + + major = addAvpFromBuffer(minor, ctx->acceptorCtx.radHandle, avps, + VENDOR_ATTR_GSS_ACCEPTOR_SERVICE_SPECIFIC, + VENDOR_ID_UKERNA, + &nameBuf); + + if (GSS_ERROR(major)) { + krb5_free_unparsed_name(krbContext, ssi); + return major; + } + krb5_free_unparsed_name(krbContext, ssi); + } + + krbDataToGssBuffer(krb5_princ_realm(krbContext, krbPrinc), &nameBuf); + if (nameBuf.length != 0) { + /* Acceptor-Realm-Name */ + major = addAvpFromBuffer(minor, ctx->acceptorCtx.radHandle, avps, + VENDOR_ATTR_GSS_ACCEPTOR_REALM_NAME, + VENDOR_ID_UKERNA, + &nameBuf); + if (GSS_ERROR(major)) + return major; + } return GSS_S_COMPLETE; } @@ -202,21 +259,25 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor, if (inputToken->length > sizeof(*pdu) && pdu->code == EAP_CODE_RESPONSE && pos[0] == EAP_TYPE_IDENTITY) { - major = importInitiatorIdentity(minor, ctx, inputToken, &nameBuf); + /* + * XXX TODO do we really need to set User-Name? FreeRADIUS does + * not appear to require it. + */ + major = addAvpFromBuffer(minor, rh, &send, PW_USER_NAME, 0, &nameBuf); if (GSS_ERROR(major)) goto cleanup; - major = addAvpFromBuffer(minor, rh, &send, PW_USER_NAME, &nameBuf); + major = setAcceptorIdentity(minor, ctx, &send); if (GSS_ERROR(major)) goto cleanup; } - major = addAvpFromBuffer(minor, rh, &send, PW_EAP_MESSAGE, inputToken); + major = addAvpFromBuffer(minor, rh, &send, PW_EAP_MESSAGE, 0, inputToken); if (GSS_ERROR(major)) goto cleanup; if (ctx->acceptorCtx.lastStatus == CHALLENGE_RC) { - major = addAvpFromBuffer(minor, rh, &send, PW_STATE, + major = addAvpFromBuffer(minor, rh, &send, PW_STATE, 0, &ctx->acceptorCtx.state); if (GSS_ERROR(major)) goto cleanup; @@ -246,14 +307,14 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor, ctx->acceptorCtx.lastStatus = code; - major = getBufferFromAvps(minor, received, PW_EAP_MESSAGE, + major = getBufferFromAvps(minor, received, PW_EAP_MESSAGE, 0, outputToken, TRUE); if ((major == GSS_S_UNAVAILABLE && code != OK_RC) || GSS_ERROR(major)) goto cleanup; if (code == CHALLENGE_RC) { - major = getBufferFromAvps(minor, received, PW_STATE, + major = getBufferFromAvps(minor, received, PW_STATE, 0, &ctx->acceptorCtx.state, TRUE); if (major != GSS_S_UNAVAILABLE && GSS_ERROR(major)) goto cleanup; @@ -331,6 +392,19 @@ eapGssSmAcceptGssChannelBindings(OM_uint32 *minor, } static OM_uint32 +eapGssSmAcceptKrbCred(OM_uint32 *minor, + gss_ctx_id_t ctx, + gss_cred_id_t cred, + gss_buffer_t inputToken, + gss_channel_bindings_t chanBindings, + gss_buffer_t outputToken) +{ + /* Called with already established context */ + *minor = EINVAL; + return GSS_S_BAD_STATUS; +} + +static OM_uint32 eapGssSmAcceptEstablished(OM_uint32 *minor, gss_ctx_id_t ctx, gss_cred_id_t cred, @@ -356,6 +430,7 @@ static struct gss_eap_acceptor_sm { { TOK_TYPE_EAP_RESP, TOK_TYPE_EAP_REQ, eapGssSmAcceptIdentity }, { TOK_TYPE_EAP_RESP, TOK_TYPE_EAP_REQ, eapGssSmAcceptAuthenticate }, { TOK_TYPE_GSS_CB, TOK_TYPE_NONE, eapGssSmAcceptGssChannelBindings }, + { TOK_TYPE_NONE, TOK_TYPE_KRB_CRED, eapGssSmAcceptKrbCred }, { TOK_TYPE_NONE, TOK_TYPE_NONE, eapGssSmAcceptEstablished }, }; @@ -448,12 +523,12 @@ gss_accept_sec_context(OM_uint32 *minor, if (major == GSS_S_COMPLETE) { if (src_name != NULL && ctx->initiatorName != GSS_C_NO_NAME) { - major = gss_duplicate_name(&tmpMinor, ctx->initiatorName, src_name); + major = gssEapDuplicateName(&tmpMinor, ctx->initiatorName, src_name); if (GSS_ERROR(major)) goto cleanup; } if (time_rec != NULL) - gss_context_time(&tmpMinor, ctx, time_rec); + gssEapContextTime(&tmpMinor, ctx, time_rec); } assert(ctx->state == EAP_STATE_ESTABLISHED || major == GSS_S_CONTINUE_NEEDED);