}
static OM_uint32
+eapGssSmAcceptGssFlags(OM_uint32 *minor,
+ gss_cred_id_t cred GSSEAP_UNUSED,
+ gss_ctx_id_t ctx,
+ gss_name_t target GSSEAP_UNUSED,
+ gss_OID mech GSSEAP_UNUSED,
+ OM_uint32 reqFlags GSSEAP_UNUSED,
+ OM_uint32 timeReq GSSEAP_UNUSED,
+ gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
+ gss_buffer_t inputToken,
+ gss_buffer_t outputToken GSSEAP_UNUSED,
+ OM_uint32 *smFlags GSSEAP_UNUSED)
+{
+ unsigned char *p;
+ OM_uint32 initiatorGssFlags;
+
+ assert((ctx->flags & CTX_FLAG_KRB_REAUTH) == 0);
+
+ if (inputToken->length < 4) {
+ *minor = GSSEAP_TOK_TRUNC;
+ return GSS_S_DEFECTIVE_TOKEN;
+ }
+
+ /* allow flags to grow for future expansion */
+ p = (unsigned char *)inputToken->value + inputToken->length - 4;
+
+ initiatorGssFlags = load_uint32_be(p);
+ initiatorGssFlags &= GSSEAP_WIRE_FLAGS_MASK;
+
+ ctx->gssFlags |= initiatorGssFlags;
+
+ return GSS_S_CONTINUE_NEEDED;
+}
+
+static OM_uint32
eapGssSmAcceptGssChannelBindings(OM_uint32 *minor,
gss_cred_id_t cred GSSEAP_UNUSED,
gss_ctx_id_t ctx,
OM_uint32 major, tmpMinor;
gss_iov_buffer_desc iov[2];
- if (ctx->flags & CTX_FLAG_KRB_REAUTH)
- return GSS_S_CONTINUE_NEEDED;
+ assert((ctx->flags & CTX_FLAG_KRB_REAUTH) == 0);
iov[0].type = GSS_IOV_BUFFER_TYPE_DATA | GSS_IOV_BUFFER_FLAG_ALLOCATE;
iov[0].buffer.length = 0;
{
OM_uint32 major;
+ assert((ctx->flags & CTX_FLAG_KRB_REAUTH) == 0);
+
major = gssEapVerifyConversationMIC(minor, ctx, inputToken);
if (GSS_ERROR(major))
return major;
eapGssSmAcceptAuthenticate
},
{
+ ITOK_TYPE_GSS_FLAGS,
+ ITOK_TYPE_NONE,
+ GSSEAP_STATE_INITIATOR_EXTS,
+ 0,
+ eapGssSmAcceptGssFlags
+ },
+ {
ITOK_TYPE_GSS_CHANNEL_BINDINGS,
ITOK_TYPE_NONE,
GSSEAP_STATE_INITIATOR_EXTS,
}
static OM_uint32
+eapGssSmInitGssFlags(OM_uint32 *minor,
+ gss_cred_id_t cred GSSEAP_UNUSED,
+ gss_ctx_id_t ctx,
+ gss_name_t target GSSEAP_UNUSED,
+ gss_OID mech GSSEAP_UNUSED,
+ OM_uint32 reqFlags GSSEAP_UNUSED,
+ OM_uint32 timeReq GSSEAP_UNUSED,
+ gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
+ gss_buffer_t inputToken GSSEAP_UNUSED,
+ gss_buffer_t outputToken,
+ OM_uint32 *smFlags GSSEAP_UNUSED)
+{
+ unsigned char wireFlags[4];
+ gss_buffer_desc flagsBuf;
+
+ store_uint32_be(ctx->gssFlags & GSSEAP_WIRE_FLAGS_MASK, wireFlags);
+
+ flagsBuf.length = sizeof(wireFlags);
+ flagsBuf.value = wireFlags;
+
+ return duplicateBuffer(minor, &flagsBuf, outputToken);
+}
+
+static OM_uint32
eapGssSmInitGssChannelBindings(OM_uint32 *minor,
gss_cred_id_t cred GSSEAP_UNUSED,
gss_ctx_id_t ctx,
gss_channel_bindings_t chanBindings,
gss_buffer_t inputToken GSSEAP_UNUSED,
gss_buffer_t outputToken,
- OM_uint32 *smFlags)
+ OM_uint32 *smFlags GSSEAP_UNUSED)
{
OM_uint32 major;
- gss_buffer_desc buffer = GSS_C_EMPTY_BUFFER;
- if (ctx->flags & CTX_FLAG_KRB_REAUTH)
- return GSS_S_CONTINUE_NEEDED;
-
- if (chanBindings != GSS_C_NO_CHANNEL_BINDINGS)
- buffer = chanBindings->application_data;
-
- major = gssEapWrap(minor, ctx, TRUE, GSS_C_QOP_DEFAULT,
- &buffer, NULL, outputToken);
- if (GSS_ERROR(major))
- return major;
-
- assert(outputToken->value != NULL);
+ if ((ctx->flags & CTX_FLAG_KRB_REAUTH) == 0 &&
+ chanBindings != GSS_C_NO_CHANNEL_BINDINGS) {
+ major = gssEapWrap(minor, ctx, TRUE, GSS_C_QOP_DEFAULT,
+ &chanBindings->application_data, NULL, outputToken);
+ if (GSS_ERROR(major))
+ return major;
+ }
*minor = 0;
- *smFlags |= SM_FLAG_OUTPUT_TOKEN_CRITICAL;
-
return GSS_S_CONTINUE_NEEDED;
}
},
{
ITOK_TYPE_NONE,
+ ITOK_TYPE_GSS_FLAGS,
+ GSSEAP_STATE_INITIATOR_EXTS,
+ 0,
+ eapGssSmInitGssFlags
+ },
+ {
+ ITOK_TYPE_NONE,
ITOK_TYPE_GSS_CHANNEL_BINDINGS,
GSSEAP_STATE_INITIATOR_EXTS,
0,
#define ITOK_TYPE_ACCEPTOR_NAME_RESP 0x00000003 /* TBD */
#define ITOK_TYPE_EAP_RESP 0x00000004 /* critical, required, if not reauth */
#define ITOK_TYPE_EAP_REQ 0x00000005 /* critical, required, if not reauth */
-#define ITOK_TYPE_GSS_CHANNEL_BINDINGS 0x00000006 /* critical, required, if not reauth */
+#define ITOK_TYPE_GSS_CHANNEL_BINDINGS 0x00000006 /* optional */
#define ITOK_TYPE_REAUTH_CREDS 0x00000007 /* optional */
#define ITOK_TYPE_REAUTH_REQ 0x00000008 /* optional */
#define ITOK_TYPE_REAUTH_RESP 0x00000009 /* optional */
-#define ITOK_TYPE_INITIATOR_MIC 0x0000000A /* required */
-#define ITOK_TYPE_ACCEPTOR_MIC 0x0000000B /* required */
-#define ITOK_TYPE_SUPPORTED_ACCEPTOR_EXTS 0x0000000C /* optional */
-#define ITOK_TYPE_SUPPORTED_INITIATOR_EXTS 0x0000000D /* optional */
-#define ITOK_TYPE_VERSION_INFO 0x0000000E /* optional */
-#define ITOK_TYPE_VENDOR_INFO 0x0000000F /* optional */
+#define ITOK_TYPE_GSS_FLAGS 0x0000000A /* optional */
+#define ITOK_TYPE_INITIATOR_MIC 0x0000000B /* required */
+#define ITOK_TYPE_ACCEPTOR_MIC 0x0000000C /* required */
+#define ITOK_TYPE_SUPPORTED_ACCEPTOR_EXTS 0x0000000D /* optional */
+#define ITOK_TYPE_SUPPORTED_INITIATOR_EXTS 0x0000000E /* optional */
+
+/* experimental */
+#define ITOK_TYPE_VERSION_INFO 0x00000080 /* optional */
+#define ITOK_TYPE_VENDOR_INFO 0x00000081 /* optional */
#define ITOK_FLAG_CRITICAL 0x80000000 /* critical, wire flag */
#define ITOK_FLAG_VERIFIED 0x40000000 /* verified, API flag */
#define ITOK_HEADER_LENGTH 8 /* type || length */
+#define GSSEAP_WIRE_FLAGS_MASK ( GSS_C_MUTUAL_FLAG )
+
OM_uint32 gssEapAllocContext(OM_uint32 *minor, gss_ctx_id_t *pCtx);
OM_uint32 gssEapReleaseContext(OM_uint32 *minor, gss_ctx_id_t *pCtx);