/*
- * Copyright (c) 2010, JANET(UK)
+ * Copyright (c) 2011, JANET(UK)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* SUCH DAMAGE.
*/
+/*
+ * Utility routines for context handles.
+ */
+
#include "gssapiP_eap.h"
OM_uint32
return GSS_S_FAILURE;
}
- ctx->state = EAP_STATE_IDENTITY;
+ ctx->state = GSSEAP_STATE_INITIAL;
/*
* Integrity, confidentiality, sequencing and replay detection are
{
OM_uint32 tmpMinor;
- if (ctx->avps != NULL)
- rc_avpair_free(ctx->avps);
- if (ctx->radHandle != NULL)
- rc_config_free(ctx->radHandle);
-
+ if (ctx->radConn != NULL)
+ rs_conn_destroy(ctx->radConn);
+ if (ctx->radContext != NULL)
+ rs_context_destroy(ctx->radContext);
+ if (ctx->radServer != NULL)
+ GSSEAP_FREE(ctx->radServer);
gss_release_buffer(&tmpMinor, &ctx->state);
+ if (ctx->vps != NULL)
+ gssEapRadiusFreeAvps(&tmpMinor, &ctx->vps);
}
OM_uint32
gssEapKerberosInit(&tmpMinor, &krbContext);
- if (ctx->flags & CTX_FLAG_KRB_REAUTH_GSS) {
+#ifdef GSSEAP_ENABLE_REAUTH
+ if (ctx->flags & CTX_FLAG_KRB_REAUTH) {
gssDeleteSecContext(&tmpMinor, &ctx->kerberosCtx, GSS_C_NO_BUFFER);
- } else if (CTX_IS_INITIATOR(ctx)) {
+ } else
+#endif
+ if (CTX_IS_INITIATOR(ctx)) {
releaseInitiatorContext(&ctx->initiatorCtx);
} else {
releaseAcceptorContext(&ctx->acceptorCtx);
krb5_free_keyblock_contents(krbContext, &ctx->rfc3961Key);
gssEapReleaseName(&tmpMinor, &ctx->initiatorName);
gssEapReleaseName(&tmpMinor, &ctx->acceptorName);
- gss_release_oid(&tmpMinor, &ctx->mechanismUsed);
+ gssEapReleaseOid(&tmpMinor, &ctx->mechanismUsed);
sequenceFree(&tmpMinor, &ctx->seqState);
+ gssEapReleaseCred(&tmpMinor, &ctx->defaultCred);
+ gss_release_buffer(&tmpMinor, &ctx->conversation);
GSSEAP_MUTEX_DESTROY(&ctx->mutex);
return GSS_S_COMPLETE;
}
-OM_uint32
-gssEapMakeToken(OM_uint32 *minor,
- gss_ctx_id_t ctx,
- const gss_buffer_t innerToken,
- enum gss_eap_token_type tokenType,
- gss_buffer_t outputToken)
+static OM_uint32
+recordTokens(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_buffer_t tokens,
+ size_t tokensCount)
{
- unsigned char *p;
+ unsigned char *buf;
+ size_t i, size, offset;
- outputToken->length = tokenSize(ctx->mechanismUsed, innerToken->length);
- outputToken->value = GSSEAP_MALLOC(outputToken->length);
- if (outputToken->value == NULL) {
+ size = ctx->conversation.length;
+
+ for (i = 0; i < tokensCount; i++)
+ size += tokens[i].length;
+
+ buf = GSSEAP_REALLOC(ctx->conversation.value, size);
+ if (buf == NULL) {
*minor = ENOMEM;
return GSS_S_FAILURE;
}
- p = (unsigned char *)outputToken->value;
- makeTokenHeader(ctx->mechanismUsed, innerToken->length, &p, tokenType);
- memcpy(p, innerToken->value, innerToken->length);
+ offset = ctx->conversation.length;
+
+ ctx->conversation.length = size;
+ ctx->conversation.value = buf;
+
+ for (i = 0; i < tokensCount; i++) {
+ memcpy(buf + offset, tokens[i].value, tokens[i].length);
+ offset += tokens[i].length;
+ }
*minor = 0;
return GSS_S_COMPLETE;
}
OM_uint32
-gssEapVerifyToken(OM_uint32 *minor,
- gss_ctx_id_t ctx,
- const gss_buffer_t inputToken,
- enum gss_eap_token_type tokenType,
- enum gss_eap_token_type *actualToken,
- gss_buffer_t innerInputToken)
+gssEapRecordContextTokenHeader(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ enum gss_eap_token_type tokType)
+{
+ unsigned char wireOidHeader[2], wireTokType[2];
+ gss_buffer_desc buffers[3];
+
+ assert(ctx->mechanismUsed != GSS_C_NO_OID);
+
+ wireOidHeader[0] = 0x06;
+ wireOidHeader[1] = ctx->mechanismUsed->length;
+ buffers[0].length = sizeof(wireOidHeader);
+ buffers[0].value = wireOidHeader;
+
+ buffers[1].length = ctx->mechanismUsed->length;
+ buffers[1].value = ctx->mechanismUsed->elements;
+
+ store_uint16_be(tokType, wireTokType);
+ buffers[2].length = sizeof(wireTokType);
+ buffers[2].value = wireTokType;
+
+ return recordTokens(minor, ctx, buffers, sizeof(buffers)/sizeof(buffers[0]));
+}
+
+OM_uint32
+gssEapRecordInnerContextToken(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_buffer_t innerToken,
+ OM_uint32 itokType)
+{
+ gss_buffer_desc buffers[3];
+ unsigned char wireItokType[4], wireLength[4];
+
+ assert(innerToken != GSS_C_NO_BUFFER);
+
+ store_uint32_be(itokType, wireItokType);
+ buffers[0].length = sizeof(wireItokType);
+ buffers[0].value = wireItokType;
+
+ store_uint32_be(innerToken->length, wireLength);
+ buffers[1].length = sizeof(wireLength);
+ buffers[1].value = wireLength;
+
+ buffers[2] = *innerToken;
+
+ return recordTokens(minor, ctx, buffers, sizeof(buffers)/sizeof(buffers[0]));
+}
+
+OM_uint32
+gssEapVerifyContextToken(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ const gss_buffer_t inputToken,
+ enum gss_eap_token_type tokType,
+ gss_buffer_t innerInputToken)
{
OM_uint32 major;
size_t bodySize;
unsigned char *p = (unsigned char *)inputToken->value;
gss_OID_desc oidBuf;
gss_OID oid;
+ enum gss_eap_token_type actualTokType;
+ gss_buffer_desc tokenBuf;
if (ctx->mechanismUsed != GSS_C_NO_OID) {
oid = ctx->mechanismUsed;
}
major = verifyTokenHeader(minor, oid, &bodySize, &p,
- inputToken->length, tokenType,
- actualToken);
+ inputToken->length, &actualTokType);
if (GSS_ERROR(major))
+ return major;
+
+ if (actualTokType != tokType) {
+ *minor = GSSEAP_WRONG_TOK_ID;
return GSS_S_DEFECTIVE_TOKEN;
+ }
if (ctx->mechanismUsed == GSS_C_NO_OID) {
- if (!gssEapIsConcreteMechanismOid(oid))
+ if (!gssEapIsConcreteMechanismOid(oid)) {
+ *minor = GSSEAP_WRONG_MECH;
return GSS_S_BAD_MECH;
+ }
if (!gssEapInternalizeOid(oid, &ctx->mechanismUsed)) {
major = duplicateOid(minor, oid, &ctx->mechanismUsed);
innerInputToken->length = bodySize;
innerInputToken->value = p;
+ /*
+ * Add OID, tokenType, body to conversation; variable length
+ * header omitted. A better API to verifyTokenHeader would
+ * avoid this ugly pointer arithmetic. XXX FIXME
+ */
+ tokenBuf.value = p - (2 + oid->length + 2);
+ tokenBuf.length = 2 + oid->length + 2 + bodySize;
+
+ major = recordTokens(minor, ctx, &tokenBuf, 1);
+ if (GSS_ERROR(major))
+ return major;
+
*minor = 0;
return GSS_S_COMPLETE;
}
gss_ctx_id_t context_handle,
OM_uint32 *time_rec)
{
- if (context_handle == GSS_C_NO_CONTEXT) {
- return GSS_S_NO_CONTEXT;
- }
-
- if (!CTX_IS_ESTABLISHED(context_handle)) {
- return GSS_S_NO_CONTEXT;
- }
-
- *minor = 0;
-
if (context_handle->expiryTime == 0) {
*time_rec = GSS_C_INDEFINITE;
} else {