+ return major;
+}
+
+#ifdef GSSEAP_ENABLE_REAUTH
+static OM_uint32
+acceptReadyKrb(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_cred_id_t cred,
+ const gss_name_t initiator,
+ const gss_OID mech,
+ OM_uint32 timeRec)
+{
+ OM_uint32 major;
+
+ major = gssEapGlueToMechName(minor, ctx, initiator, &ctx->initiatorName);
+ if (GSS_ERROR(major))
+ return major;
+
+ major = gssEapReauthComplete(minor, ctx, cred, mech, timeRec);
+ if (GSS_ERROR(major))
+ return major;
+
+ *minor = 0;
+ return GSS_S_COMPLETE;
+}
+
+static OM_uint32
+eapGssSmAcceptGssReauth(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ gss_ctx_id_t ctx,
+ gss_name_t target GSSEAP_UNUSED,
+ gss_OID mech,
+ OM_uint32 reqFlags GSSEAP_UNUSED,
+ OM_uint32 timeReq GSSEAP_UNUSED,
+ gss_channel_bindings_t chanBindings,
+ gss_buffer_t inputToken,
+ gss_buffer_t outputToken,
+ OM_uint32 *smFlags)
+{
+ OM_uint32 major, tmpMinor;
+ gss_name_t krbInitiator = GSS_C_NO_NAME;
+ OM_uint32 gssFlags, timeRec = GSS_C_INDEFINITE;
+
+ /*
+ * If we're built with fast reauthentication support, it's valid
+ * for an initiator to send a GSS reauthentication token as its
+ * initial context token, causing us to short-circuit the state
+ * machine and process Kerberos GSS messages instead.
+ */
+
+ ctx->flags |= CTX_FLAG_KRB_REAUTH;
+
+ major = gssAcceptSecContext(minor,
+ &ctx->kerberosCtx,
+ cred->krbCred,
+ inputToken,
+ chanBindings,
+ &krbInitiator,
+ &mech,
+ outputToken,
+ &gssFlags,
+ &timeRec,
+ NULL);
+ if (major == GSS_S_COMPLETE) {
+ major = acceptReadyKrb(minor, ctx, cred,
+ krbInitiator, mech, timeRec);
+ if (major == GSS_S_COMPLETE) {
+ GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_ESTABLISHED);
+ }
+ ctx->gssFlags = gssFlags;
+ } else if (GSS_ERROR(major) &&
+ (*smFlags & SM_FLAG_INPUT_TOKEN_CRITICAL) == 0) {
+ /* pretend reauthentication attempt never happened */
+ gssDeleteSecContext(&tmpMinor, &ctx->kerberosCtx, GSS_C_NO_BUFFER);
+ ctx->flags &= ~(CTX_FLAG_KRB_REAUTH);
+ GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_INITIAL);
+ major = GSS_S_CONTINUE_NEEDED;
+ }
+
+ gssReleaseName(&tmpMinor, &krbInitiator);