return GSS_S_BAD_STATUS;
}
+static OM_uint32
+makeErrorToken(OM_uint32 *minor,
+ OM_uint32 majorStatus,
+ OM_uint32 minorStatus,
+ gss_buffer_t outputToken)
+{
+ unsigned char errorData[8];
+ gss_buffer_desc errorBuffer;
+
+ store_uint32_be(majorStatus, &errorData[0]);
+ store_uint32_be(minorStatus, &errorData[4]);
+
+ errorBuffer.length = sizeof(errorData);
+ errorBuffer.value = errorData;
+
+ return duplicateBuffer(minor, &errorBuffer, outputToken);
+}
+
static struct gss_eap_acceptor_sm {
enum gss_eap_token_type inputTokenType;
enum gss_eap_token_type outputTokenType;
gss_channel_bindings_t,
gss_buffer_t);
} eapGssAcceptorSm[] = {
- { TOK_TYPE_EAP_RESP, TOK_TYPE_EAP_REQ, eapGssSmAcceptIdentity },
- { TOK_TYPE_EAP_RESP, TOK_TYPE_EAP_REQ, eapGssSmAcceptAuthenticate },
- { TOK_TYPE_EXT_REQ, TOK_TYPE_NONE, eapGssSmAcceptExtensionsReq },
- { TOK_TYPE_NONE, TOK_TYPE_EXT_RESP, eapGssSmAcceptExtensionsResp },
- { TOK_TYPE_NONE, TOK_TYPE_NONE, eapGssSmAcceptEstablished },
+ { TOK_TYPE_EAP_RESP, TOK_TYPE_EAP_REQ, eapGssSmAcceptIdentity },
+ { TOK_TYPE_EAP_RESP, TOK_TYPE_EAP_REQ, eapGssSmAcceptAuthenticate },
+ { TOK_TYPE_EXT_REQ, TOK_TYPE_NONE, eapGssSmAcceptExtensionsReq },
+ { TOK_TYPE_NONE, TOK_TYPE_EXT_RESP, eapGssSmAcceptExtensionsResp },
+ { TOK_TYPE_NONE, TOK_TYPE_NONE, eapGssSmAcceptEstablished },
+ { TOK_TYPE_NONE, TOK_TYPE_CONTEXT_ERR, NULL },
#ifdef GSSEAP_ENABLE_REAUTH
- { TOK_TYPE_GSS_REAUTH, TOK_TYPE_GSS_REAUTH, eapGssSmAcceptGssReauth },
+ { TOK_TYPE_GSS_REAUTH, TOK_TYPE_GSS_REAUTH, eapGssSmAcceptGssReauth },
#endif
};
&innerInputToken,
input_chan_bindings,
&innerOutputToken);
- if (GSS_ERROR(major))
- goto cleanup;
+ if (GSS_ERROR(major)) {
+ /* Generate an error token */
+ tmpMajor = makeErrorToken(&tmpMinor, major, *minor, &innerOutputToken);
+ if (GSS_ERROR(tmpMajor)) {
+ major = tmpMajor;
+ goto cleanup;
+ }
+
+ sm = &eapGssAcceptorSm[EAP_STATE_ERROR];
+ goto send_token;
+ }
} while (major == GSS_S_CONTINUE_NEEDED && innerOutputToken.length == 0);
if (mech_type != NULL) {
if (!gssEapInternalizeOid(ctx->mechanismUsed, mech_type))
duplicateOid(&tmpMinor, ctx->mechanismUsed, mech_type);
}
- if (innerOutputToken.value != NULL) {
- tmpMajor = gssEapMakeToken(&tmpMinor, ctx, &innerOutputToken,
- sm->outputTokenType, output_token);
- if (GSS_ERROR(tmpMajor)) {
- major = tmpMajor;
- *minor = tmpMinor;
- goto cleanup;
- }
- }
if (ret_flags != NULL)
*ret_flags = ctx->gssFlags;
if (delegated_cred_handle != NULL)
assert(ctx->state == EAP_STATE_ESTABLISHED || major == GSS_S_CONTINUE_NEEDED);
+send_token:
+ if (innerOutputToken.value != NULL) {
+ tmpMajor = gssEapMakeToken(&tmpMinor, ctx, &innerOutputToken,
+ sm->outputTokenType, output_token);
+ if (GSS_ERROR(tmpMajor)) {
+ major = tmpMajor;
+ *minor = tmpMinor;
+ goto cleanup;
+ }
+ }
+
cleanup:
if (cred != GSS_C_NO_CREDENTIAL)
GSSEAP_MUTEX_UNLOCK(&cred->mutex);
EAP_STATE_EXTENSIONS_REQ,
EAP_STATE_EXTENSIONS_RESP,
EAP_STATE_ESTABLISHED,
+ EAP_STATE_ERROR,
#ifdef GSSEAP_ENABLE_REAUTH
EAP_STATE_KRB_REAUTH_GSS
#endif
error_code GSSEAP_MISSING_IOV, "IOV is missing required buffer"
error_code GSSEAP_BAD_STREAM_IOV, "Stream IOV can only contain a single data buffer"
error_code GSSEAP_BAD_PRF_KEY, "PRF key usage type is unknown"
+error_code GSSEAP_BAD_ERROR_TOKEN, "Error token is malformed or corrupt"
end
return GSS_S_BAD_STATUS;
}
+static OM_uint32
+eapGssSmInitError(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ gss_ctx_id_t ctx,
+ gss_name_t target,
+ gss_OID mech,
+ OM_uint32 reqFlags,
+ OM_uint32 timeReq,
+ gss_channel_bindings_t chanBindings,
+ gss_buffer_t inputToken,
+ gss_buffer_t outputToken)
+{
+ OM_uint32 major;
+ unsigned char *p;
+
+ if (inputToken->length < 8) {
+ *minor = GSSEAP_WRONG_SIZE;
+ return GSS_S_DEFECTIVE_TOKEN;
+ }
+
+ p = (unsigned char *)inputToken->value;
+
+ major = load_uint32_be(&p[0]);
+ *minor = load_uint32_be(&p[4]);
+
+ if (!GSS_ERROR(major)) {
+ *minor = GSSEAP_BAD_ERROR_TOKEN;
+ major = GSS_S_FAILURE;
+ }
+
+ return major;
+}
+
static struct gss_eap_initiator_sm {
enum gss_eap_token_type inputTokenType;
enum gss_eap_token_type outputTokenType;
gss_buffer_t,
gss_buffer_t);
} eapGssInitiatorSm[] = {
- { TOK_TYPE_NONE, TOK_TYPE_EAP_RESP, eapGssSmInitIdentity },
- { TOK_TYPE_EAP_REQ, TOK_TYPE_EAP_RESP, eapGssSmInitAuthenticate },
- { TOK_TYPE_NONE, TOK_TYPE_EXT_REQ, eapGssSmInitExtensionsReq },
- { TOK_TYPE_EXT_RESP,TOK_TYPE_NONE, eapGssSmInitExtensionsResp },
- { TOK_TYPE_NONE, TOK_TYPE_NONE, eapGssSmInitEstablished },
+ { TOK_TYPE_NONE, TOK_TYPE_EAP_RESP, eapGssSmInitIdentity },
+ { TOK_TYPE_EAP_REQ, TOK_TYPE_EAP_RESP, eapGssSmInitAuthenticate },
+ { TOK_TYPE_NONE, TOK_TYPE_EXT_REQ, eapGssSmInitExtensionsReq },
+ { TOK_TYPE_EXT_RESP, TOK_TYPE_NONE, eapGssSmInitExtensionsResp },
+ { TOK_TYPE_NONE, TOK_TYPE_NONE, eapGssSmInitEstablished },
+ { TOK_TYPE_CONTEXT_ERR, TOK_TYPE_NONE, eapGssSmInitError },
#ifdef GSSEAP_ENABLE_REAUTH
- { TOK_TYPE_GSS_REAUTH, TOK_TYPE_GSS_REAUTH, eapGssSmInitGssReauth },
+ { TOK_TYPE_GSS_REAUTH, TOK_TYPE_GSS_REAUTH, eapGssSmInitGssReauth },
#endif
};
if (GSS_ERROR(major))
goto cleanup;
- if (tokType != sm->inputTokenType) {
+ if (tokType == TOK_TYPE_CONTEXT_ERR) {
+ ctx->state = EAP_STATE_ERROR;
+ } else if (tokType != sm->inputTokenType) {
*minor = GSSEAP_WRONG_TOK_ID;
major = GSS_S_DEFECTIVE_TOKEN;
goto cleanup;
TOK_TYPE_MIC = 0x0404, /* RFC 4121 MIC token */
TOK_TYPE_WRAP = 0x0504, /* RFC 4121 wrap token */
TOK_TYPE_EXPORT_NAME = 0x0401, /* RFC 2743 exported name */
- TOK_TYPE_EXPORT_NAME_COMPOSITE = 0x0402, /* draft-ietf-kitten-gss-naming */
+ TOK_TYPE_EXPORT_NAME_COMPOSITE = 0x0402, /* exported composite name */
TOK_TYPE_DELETE_CONTEXT = 0x0405, /* RFC 2743 delete context */
- TOK_TYPE_EAP_RESP = 0x0601, /* draft-howlett-eap-gss */
- TOK_TYPE_EAP_REQ = 0x0602, /* draft-howlett-eap-gss */
- TOK_TYPE_EXT_REQ = 0x0603, /* draft-howlett-eap-gss */
- TOK_TYPE_EXT_RESP = 0x0604, /* to be specified */
- TOK_TYPE_GSS_REAUTH = 0x0605, /* to be specified */
+ TOK_TYPE_EAP_RESP = 0x0601, /* EAP response */
+ TOK_TYPE_EAP_REQ = 0x0602, /* EAP request */
+ TOK_TYPE_EXT_REQ = 0x0603, /* GSS EAP extensions request */
+ TOK_TYPE_EXT_RESP = 0x0604, /* GSS EAP extensions response */
+ TOK_TYPE_GSS_REAUTH = 0x0605, /* GSS EAP fast reauthentication token */
+ TOK_TYPE_CONTEXT_ERR = 0x0606, /* context error */
};
#define EAP_EXPORT_CONTEXT_V1 1