#define SM_FLAG_TRANSITED 0x80000000
#define SM_ASSERT_VALID(ctx, status) do { \
- assert(GSS_ERROR((status)) || \
+ GSSEAP_ASSERT(GSS_ERROR((status)) || \
((status) == GSS_S_CONTINUE_NEEDED && ((ctx)->state > GSSEAP_STATE_INITIAL && (ctx)->state < GSSEAP_STATE_ESTABLISHED)) || \
((status) == GSS_S_COMPLETE && (ctx)->state == GSSEAP_STATE_ESTABLISHED)); \
} while (0)
void
gssEapSmTransition(gss_ctx_id_t ctx, enum gss_eap_state state)
{
- assert(state >= GSSEAP_STATE_INITIAL);
- assert(state <= GSSEAP_STATE_ESTABLISHED);
+ GSSEAP_ASSERT(state >= GSSEAP_STATE_INITIAL);
+ GSSEAP_ASSERT(state <= GSSEAP_STATE_ESTABLISHED);
fprintf(stderr, "GSS-EAP: state transition %s->%s\n",
gssEapStateToString(GSSEAP_SM_STATE(ctx)),
makeErrorToken(OM_uint32 *minor,
OM_uint32 majorStatus,
OM_uint32 minorStatus,
- gss_buffer_set_t *outputToken)
+ struct gss_eap_token_buffer_set *token)
{
- OM_uint32 major;
+ OM_uint32 major, tmpMinor;
unsigned char errorData[8];
gss_buffer_desc errorBuffer;
- assert(GSS_ERROR(majorStatus));
-
- major = gss_create_empty_buffer_set(minor, outputToken);
- if (GSS_ERROR(major))
- return major;
+ GSSEAP_ASSERT(GSS_ERROR(majorStatus));
/*
* Only return error codes that the initiator could have caused,
minorStatus = GSSEAP_RADIUS_PROT_FAILURE;
} else if (!IS_WIRE_ERROR(minorStatus)) {
/* Don't return non-wire error codes */
- return GSS_S_COMPLETE;
+ minorStatus = 0;
}
- minorStatus -= ERROR_TABLE_BASE_eapg;
+ if (minorStatus != 0)
+ minorStatus -= ERROR_TABLE_BASE_eapg;
store_uint32_be(majorStatus, &errorData[0]);
store_uint32_be(minorStatus, &errorData[4]);
- errorBuffer.length = sizeof(errorData);
- errorBuffer.value = errorData;
-
- major = gss_add_buffer_set_member(minor, &errorBuffer, outputToken);
- if (GSS_ERROR(major))
+ major = gssEapAllocInnerTokens(&tmpMinor, 1, token);
+ if (GSS_ERROR(major)) {
+ *minor = tmpMinor;
return major;
-
- return GSS_S_COMPLETE;
-}
-
-static OM_uint32
-allocInnerTokens(OM_uint32 *minor,
- size_t count,
- gss_buffer_set_t *pTokens,
- OM_uint32 **pTokenTypes)
-{
- OM_uint32 major, tmpMinor;
- gss_buffer_set_t tokens = GSS_C_NO_BUFFER_SET;
- OM_uint32 *tokenTypes = NULL;
-
- major = gss_create_empty_buffer_set(minor, &tokens);
- if (GSS_ERROR(major))
- goto cleanup;
-
- assert(tokens->count == 0);
- assert(tokens->elements == NULL);
-
- tokens->elements = (gss_buffer_desc *)GSSEAP_CALLOC(count, sizeof(gss_buffer_desc));
- if (tokens->elements == NULL) {
- major = GSS_S_FAILURE;
- *minor = ENOMEM;
- goto cleanup;
- }
-
- tokenTypes = (OM_uint32 *)GSSEAP_CALLOC(count, sizeof(OM_uint32));
- if (tokenTypes == NULL) {
- major = GSS_S_FAILURE;
- *minor = ENOMEM;
- goto cleanup;
}
- major = GSS_S_COMPLETE;
- *minor = 0;
+ errorBuffer.length = sizeof(errorData);
+ errorBuffer.value = errorData;
-cleanup:
+ major = duplicateBuffer(&tmpMinor, &errorBuffer, &token->buffers.elements[0]);
if (GSS_ERROR(major)) {
- gss_release_buffer_set(&tmpMinor, &tokens);
- tokens = GSS_C_NO_BUFFER_SET;
- if (tokenTypes != NULL) {
- GSSEAP_FREE(tokenTypes);
- tokenTypes = NULL;
- }
+ gssEapReleaseInnerTokens(&tmpMinor, token, 1);
+ *minor = tmpMinor;
+ return major;
}
- *pTokens = tokens;
- *pTokenTypes = tokenTypes;
+ token->buffers.count = 1;
+ token->types[0] = ITOK_TYPE_CONTEXT_ERR | ITOK_FLAG_CRITICAL;
- return major;
+ *minor = 0;
+ return GSS_S_COMPLETE;
}
OM_uint32
gssEapSmStep(OM_uint32 *minor,
gss_cred_id_t cred,
gss_ctx_id_t ctx,
- gss_name_t target,
+ gss_const_name_t target,
gss_OID mech,
OM_uint32 reqFlags,
OM_uint32 timeReq,
size_t smCount)
{
OM_uint32 major, tmpMajor, tmpMinor;
+ struct gss_eap_token_buffer_set inputTokens = { { 0, GSS_C_NO_BUFFER }, NULL };
+ struct gss_eap_token_buffer_set outputTokens = { { 0, GSS_C_NO_BUFFER }, NULL };
gss_buffer_desc unwrappedInputToken = GSS_C_EMPTY_BUFFER;
gss_buffer_desc unwrappedOutputToken = GSS_C_EMPTY_BUFFER;
- gss_buffer_set_t innerInputTokens = GSS_C_NO_BUFFER_SET;
- gss_buffer_set_t innerOutputTokens = GSS_C_NO_BUFFER_SET;
- OM_uint32 *inputTokenTypes = NULL, *outputTokenTypes = NULL;
unsigned int smFlags = 0;
size_t i, j;
int initialContextToken = 0;
enum gss_eap_token_type tokType;
- assert(smCount > 0);
+ GSSEAP_ASSERT(smCount > 0);
*minor = 0;
goto cleanup;
}
- assert(ctx->state < GSSEAP_STATE_ESTABLISHED);
+ GSSEAP_ASSERT(ctx->state < GSSEAP_STATE_ESTABLISHED);
- major = gssEapDecodeInnerTokens(minor, &unwrappedInputToken,
- &innerInputTokens, &inputTokenTypes);
+ major = gssEapDecodeInnerTokens(minor, &unwrappedInputToken, &inputTokens);
if (GSS_ERROR(major))
goto cleanup;
- assert(innerInputTokens != GSS_C_NO_BUFFER_SET);
-
- major = allocInnerTokens(minor, smCount, &innerOutputTokens, &outputTokenTypes);
+ major = gssEapAllocInnerTokens(minor, smCount, &outputTokens);
if (GSS_ERROR(major))
goto cleanup;
+ ctx->inputTokens = &inputTokens;
+ ctx->outputTokens = &outputTokens;
+
/* Process all the tokens that are valid for the current state. */
for (i = 0; i < smCount; i++) {
struct gss_eap_sm *smp = &sm[i];
processToken = 1;
} else if ((smFlags & SM_FLAG_TRANSITED) == 0) {
/* Don't regurgitate a token which belonds to a previous state. */
- for (j = 0; j < innerInputTokens->count; j++) {
- if ((inputTokenTypes[j] & ITOK_TYPE_MASK) == smp->inputTokenType) {
+ for (j = 0; j < inputTokens.buffers.count; j++) {
+ if ((inputTokens.types[j] & ITOK_TYPE_MASK) == smp->inputTokenType) {
if (processToken) {
/* Check for duplicate inner tokens */
major = GSS_S_DEFECTIVE_TOKEN;
break;
}
processToken = 1;
- innerInputToken = &innerInputTokens->elements[j];
- inputTokenType = &inputTokenTypes[j];
+ innerInputToken = &inputTokens.buffers.elements[j];
+ inputTokenType = &inputTokens.types[j];
}
}
if (GSS_ERROR(major))
smFlags |= SM_FLAG_TRANSITED;
if (innerOutputToken.value != NULL) {
- innerOutputTokens->elements[innerOutputTokens->count] = innerOutputToken;
- assert(smp->outputTokenType != ITOK_TYPE_NONE);
- outputTokenTypes[innerOutputTokens->count] = smp->outputTokenType;
+ outputTokens.buffers.elements[outputTokens.buffers.count] = innerOutputToken;
+ GSSEAP_ASSERT(smp->outputTokenType != ITOK_TYPE_NONE);
+ outputTokens.types[outputTokens.buffers.count] = smp->outputTokenType;
if (smFlags & SM_FLAG_OUTPUT_TOKEN_CRITICAL)
- outputTokenTypes[innerOutputTokens->count] |= ITOK_FLAG_CRITICAL;
- innerOutputTokens->count++;
+ outputTokens.types[outputTokens.buffers.count] |= ITOK_FLAG_CRITICAL;
+ outputTokens.buffers.count++;
}
/*
* Break out if we made a state transition and have some tokens to send.
*/
if ((smFlags & SM_FLAG_TRANSITED) &&
- ((smFlags & SM_FLAG_FORCE_SEND_TOKEN) || innerOutputTokens->count != 0)) {
+ ((smFlags & SM_FLAG_FORCE_SEND_TOKEN) || outputTokens.buffers.count != 0)) {
SM_ASSERT_VALID(ctx, major);
break;
}
}
}
- assert(innerOutputTokens->count <= smCount);
+ GSSEAP_ASSERT(outputTokens.buffers.count <= smCount);
/* Check we understood all critical tokens sent by peer */
if (!GSS_ERROR(major)) {
- for (j = 0; j < innerInputTokens->count; j++) {
- if ((inputTokenTypes[j] & ITOK_FLAG_CRITICAL) &&
- (inputTokenTypes[j] & ITOK_FLAG_VERIFIED) == 0) {
+ for (j = 0; j < inputTokens.buffers.count; j++) {
+ if ((inputTokens.types[j] & ITOK_FLAG_CRITICAL) &&
+ (inputTokens.types[j] & ITOK_FLAG_VERIFIED) == 0) {
major = GSS_S_UNAVAILABLE;
*minor = GSSEAP_CRIT_ITOK_UNAVAILABLE;
goto cleanup;
goto cleanup; /* return error directly to caller */
/* replace any emitted tokens with error token */
- gss_release_buffer_set(&tmpMinor, &innerOutputTokens);
+ gssEapReleaseInnerTokens(&tmpMinor, &outputTokens, 1);
- tmpMajor = makeErrorToken(&tmpMinor, major, *minor, &innerOutputTokens);
+ tmpMajor = makeErrorToken(&tmpMinor, major, *minor, &outputTokens);
if (GSS_ERROR(tmpMajor)) {
major = tmpMajor;
*minor = tmpMinor;
goto cleanup;
}
-
- if (innerOutputTokens->count != 0)
- outputTokenTypes[0] = ITOK_TYPE_CONTEXT_ERR | ITOK_FLAG_CRITICAL;
}
/* Format output token from inner tokens */
- if (innerOutputTokens->count != 0 || /* inner tokens to send */
+ if (outputTokens.buffers.count != 0 || /* inner tokens to send */
!CTX_IS_INITIATOR(ctx) || /* any leg acceptor */
!CTX_IS_ESTABLISHED(ctx)) { /* non-last leg initiator */
- tmpMajor = gssEapEncodeInnerTokens(&tmpMinor, innerOutputTokens,
- outputTokenTypes, &unwrappedOutputToken);
+ tmpMajor = gssEapEncodeInnerTokens(&tmpMinor, &outputTokens, &unwrappedOutputToken);
if (tmpMajor == GSS_S_COMPLETE) {
if (CTX_IS_INITIATOR(ctx))
tokType = TOK_TYPE_INITIATOR_CONTEXT;
}
/* If the context is established, empty tokens only to be emitted by initiator */
- assert(!CTX_IS_ESTABLISHED(ctx) || ((outputToken->length == 0) == CTX_IS_INITIATOR(ctx)));
+ GSSEAP_ASSERT(!CTX_IS_ESTABLISHED(ctx) || ((outputToken->length == 0) == CTX_IS_INITIATOR(ctx)));
SM_ASSERT_VALID(ctx, major);
cleanup:
- gss_release_buffer_set(&tmpMinor, &innerInputTokens);
- gss_release_buffer_set(&tmpMinor, &innerOutputTokens);
- if (inputTokenTypes != NULL)
- GSSEAP_FREE(inputTokenTypes);
- if (outputTokenTypes != NULL)
+ gssEapReleaseInnerTokens(&tmpMinor, &inputTokens, 0);
+ gssEapReleaseInnerTokens(&tmpMinor, &inputTokens, 1);
+
gss_release_buffer(&tmpMinor, &unwrappedOutputToken);
- GSSEAP_FREE(outputTokenTypes);
+
+ ctx->inputTokens = NULL;
+ ctx->outputTokens = NULL;
return major;
}