ctx->flags |= CTX_FLAG_KRB_REAUTH;
+ /*
+ * To avoid an additional round trip, we use GSS channel bindings
+ * to integrity protect the rest of the initiator exchange. This
+ * does have the disadvantage of making it impossible for the
+ * acceptor to ignore application channel bindings, behaviour
+ * which differs from normal Kerberos and GSS-EAP itself.
+ */
+ major = gssEapMakeTokenChannelBindings(minor, ctx,
+ userChanBindings,
+ inputToken,
+ &wireChanBindings);
+ if (GSS_ERROR(major))
+ return major;
+
major = gssAcceptSecContext(minor,
- &ctx->kerberosCtx,
+ &ctx->reauthCtx,
cred->krbCred,
inputToken,
- chanBindings,
+ &wireChanBindings,
&krbInitiator,
&mech,
outputToken,
ctx->gssFlags = gssFlags;
} else if (GSS_ERROR(major) &&
(*smFlags & SM_FLAG_INPUT_TOKEN_CRITICAL) == 0) {
- /* pretend reauthentication attempt never happened */
+ /* Fall back to EAP */
- gssDeleteSecContext(&tmpMinor, &ctx->kerberosCtx, GSS_C_NO_BUFFER);
+ gssDeleteSecContext(&tmpMinor, &ctx->reauthCtx, GSS_C_NO_BUFFER);
ctx->flags &= ~(CTX_FLAG_KRB_REAUTH);
GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_INITIAL);
- major = GSS_S_CONTINUE_NEEDED;
+ } else {
+ GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_REAUTHENTICATE);
}
+ major = GSS_S_CONTINUE_NEEDED;
+
gssReleaseName(&tmpMinor, &krbInitiator);
+ gss_release_buffer(&tmpMinor, &wireChanBindings.application_data);
return major;
}
struct gss_eap_acceptor_ctx acceptor;
#define acceptorCtx ctxU.acceptor
#ifdef GSSEAP_ENABLE_REAUTH
- gss_ctx_id_t kerberos;
- #define kerberosCtx ctxU.kerberos
+ gss_ctx_id_t reauth;
+ #define reauthCtx ctxU.reauth
#endif
} ctxU;
+ gss_buffer_desc conversation;
};
#define TOK_FLAG_SENDER_IS_ACCEPTOR 0x01