GLchar *loadShader(char *filename){ GLchar *charBuf = calloc(CHARBUFSIZE,sizeof(GLchar)); if (charBuf == NULL) return NULL; FILE *shader; int bufIndex = 0; int sourceBufSize = CHARBUFSIZE; shader = fopen(filename,"r"); if (shader == NULL){ free(charBuf); return NULL; }else{ while(!feof(shader)){ charBuf[bufIndex] = (GLchar) fgetc(shader); bufIndex += 1; if ((bufIndex % CHARBUFMAXIDX) == 0){ if (duplicateBuffer(charBuf,sourceBufSize) >= 0){ sourceBufSize = sourceBufSize*2; }else{ free(charBuf); return NULL; } } } fclose(shader); charBuf[bufIndex-1] = '\0'; return charBuf; } }
OM_uint32 gssEapSetCredDelegAssertions(OM_uint32 *minor, gss_cred_id_t cred, const gss_buffer_t deleg_assertions) { OM_uint32 major, tmpMinor; gss_buffer_desc newAssertions = GSS_C_EMPTY_BUFFER; if (cred->flags & CRED_FLAG_RESOLVED) { major = GSS_S_FAILURE; *minor = GSSEAP_CRED_RESOLVED; goto cleanup; } if (deleg_assertions != GSS_C_NO_BUFFER) { major = duplicateBuffer(minor, deleg_assertions, &newAssertions); if (GSS_ERROR(major)) goto cleanup; } gss_release_buffer(&tmpMinor, &cred->deleg_assertions); cred->deleg_assertions = newAssertions; major = GSS_S_COMPLETE; *minor = 0; cleanup: return major; }
OM_uint32 gssEapSetCredPassword(OM_uint32 *minor, gss_cred_id_t cred, const gss_buffer_t password) { OM_uint32 major, tmpMinor; gss_buffer_desc newPassword = GSS_C_EMPTY_BUFFER; if (cred->flags & CRED_FLAG_RESOLVED) { major = GSS_S_FAILURE; *minor = GSSEAP_CRED_RESOLVED; goto cleanup; } if (password != GSS_C_NO_BUFFER) { major = duplicateBuffer(minor, password, &newPassword); if (GSS_ERROR(major)) goto cleanup; cred->flags |= CRED_FLAG_PASSWORD; } else { cred->flags &= ~(CRED_FLAG_PASSWORD); } gss_release_buffer(&tmpMinor, &cred->password); cred->password = newPassword; major = GSS_S_COMPLETE; *minor = 0; cleanup: return major; }
static OM_uint32 gssEapImportPartialContext(OM_uint32 *minor, unsigned char **pBuf, size_t *pRemain, gss_ctx_id_t ctx) { OM_uint32 major; unsigned char *p = *pBuf; size_t remain = *pRemain; gss_buffer_desc buf; size_t ctxLength, serverLen; /* Length of partial RADIUS context */ CHECK_REMAIN(4); ctxLength = load_uint32_be(p); UPDATE_REMAIN(4); CHECK_REMAIN(ctxLength); remain = ctxLength; /* check against partial context length */ /* Selected RADIUS server */ CHECK_REMAIN(4); serverLen = load_uint32_be(p); UPDATE_REMAIN(4); if (serverLen != 0) { CHECK_REMAIN(serverLen); ctx->acceptorCtx.radServer = GSSEAP_MALLOC(serverLen + 1); if (ctx->acceptorCtx.radServer == NULL) { *minor = ENOMEM; return GSS_S_FAILURE; } memcpy(ctx->acceptorCtx.radServer, p, serverLen); ctx->acceptorCtx.radServer[serverLen] = '\0'; UPDATE_REMAIN(serverLen); } /* RADIUS state blob */ CHECK_REMAIN(4); buf.length = load_uint32_be(p); UPDATE_REMAIN(4); if (buf.length != 0) { CHECK_REMAIN(buf.length); buf.value = p; major = duplicateBuffer(minor, &buf, &ctx->acceptorCtx.state); if (GSS_ERROR(major)) return major; UPDATE_REMAIN(buf.length); } #ifdef GSSEAP_DEBUG GSSEAP_ASSERT(remain == 0); #endif *pBuf = p; *pRemain -= 4 + ctxLength; return GSS_S_COMPLETE; }
bool gss_eap_radius_attr_provider::getAttribute(const gss_eap_attrid &attrid, int *authenticated, int *complete, gss_buffer_t value, gss_buffer_t display_value, int *more) const { rs_const_avp *vp; int i = *more, count = 0; *more = 0; if (i == -1) i = 0; if (isSecretAttributeP(attrid) || isInternalAttributeP(attrid)) { return false; } else if (isFragmentedAttributeP(attrid)) { return getFragmentedAttribute(attrid, authenticated, complete, value); } for (vp = rs_avp_find_const(m_vps, attrid.second, attrid.first); vp != NULL; vp = rs_avp_find_const(rs_avp_next_const(vp), attrid.second, attrid.first)) { if (count++ == i) { if (rs_avp_find_const(rs_avp_next_const(vp), attrid.second, attrid.first) != NULL) *more = count; break; } } if (vp == NULL && *more == 0) return false; if (value != GSS_C_NO_BUFFER) { gss_buffer_desc valueBuf; rs_avp_octets_value_byref((rs_avp *)vp, (unsigned char **)&valueBuf.value, &valueBuf.length); duplicateBuffer(valueBuf, value); } if (display_value != GSS_C_NO_BUFFER && !rs_avp_is_octets(vp)) { char displayString[RS_MAX_STRING_LEN]; gss_buffer_desc displayBuf; displayBuf.length = rs_avp_display_value(vp, displayString, sizeof(displayString)); displayBuf.value = (void *)displayString; duplicateBuffer(displayBuf, display_value); } if (authenticated != NULL) *authenticated = m_authenticated; if (complete != NULL) *complete = true; return true; }
static OM_uint32 makeErrorToken(OM_uint32 *minor, OM_uint32 majorStatus, OM_uint32 minorStatus, struct gss_eap_token_buffer_set *token) { OM_uint32 major, tmpMinor; unsigned char errorData[8]; gss_buffer_desc errorBuffer; GSSEAP_ASSERT(GSS_ERROR(majorStatus)); /* * Only return error codes that the initiator could have caused, * to avoid information leakage. */ #if MECH_EAP if (IS_RADIUS_ERROR(minorStatus)) { /* Squash RADIUS error codes */ minorStatus = GSSEAP_RADIUS_PROT_FAILURE; } else if (!IS_WIRE_ERROR(minorStatus)) { #else if (!IS_WIRE_ERROR(minorStatus)) { #endif /* Don't return non-wire error codes */ return GSS_S_COMPLETE; } minorStatus -= ERROR_TABLE_BASE_eapg; store_uint32_be(majorStatus, &errorData[0]); store_uint32_be(minorStatus, &errorData[4]); major = gssEapAllocInnerTokens(&tmpMinor, 1, token); if (GSS_ERROR(major)) { *minor = tmpMinor; return major; } errorBuffer.length = sizeof(errorData); errorBuffer.value = errorData; major = duplicateBuffer(&tmpMinor, &errorBuffer, &token->buffers.elements[0]); if (GSS_ERROR(major)) { gssEapReleaseInnerTokens(&tmpMinor, token, 1); *minor = tmpMinor; return major; } token->buffers.count = 1; token->types[0] = ITOK_TYPE_CONTEXT_ERR | ITOK_FLAG_CRITICAL; *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_OID mech, OM_uint32 reqFlags, OM_uint32 timeReq, gss_channel_bindings_t chanBindings, gss_buffer_t inputToken, gss_buffer_t outputToken, struct gss_eap_sm *sm, /* ordered by state */ 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; unsigned int smFlags = 0; size_t i, j; int initialContextToken = 0; enum gss_eap_token_type tokType; GSSEAP_ASSERT(smCount > 0); *minor = 0; outputToken->length = 0; outputToken->value = NULL; if (inputToken != GSS_C_NO_BUFFER && inputToken->length != 0) { major = gssEapVerifyToken(minor, ctx, inputToken, &tokType, &unwrappedInputToken); if (GSS_ERROR(major)) goto cleanup; if (tokType != (CTX_IS_INITIATOR(ctx) ? TOK_TYPE_ACCEPTOR_CONTEXT : TOK_TYPE_INITIATOR_CONTEXT)) { major = GSS_S_DEFECTIVE_TOKEN; *minor = GSSEAP_WRONG_TOK_ID; goto cleanup; } } else if (!CTX_IS_INITIATOR(ctx) || ctx->state != GSSEAP_STATE_INITIAL) { major = GSS_S_DEFECTIVE_TOKEN; *minor = GSSEAP_WRONG_SIZE; goto cleanup; } else { initialContextToken = 1; } if (CTX_IS_ESTABLISHED(ctx)) { major = GSS_S_BAD_STATUS; *minor = GSSEAP_CONTEXT_ESTABLISHED; goto cleanup; } GSSEAP_ASSERT(ctx->state < GSSEAP_STATE_ESTABLISHED); major = gssEapDecodeInnerTokens(minor, &unwrappedInputToken, &inputTokens); if (GSS_ERROR(major)) goto cleanup; 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]; int processToken = 0; gss_buffer_t innerInputToken = GSS_C_NO_BUFFER; OM_uint32 *inputTokenType = NULL; gss_buffer_desc innerOutputToken = GSS_C_EMPTY_BUFFER; if ((smp->validStates & ctx->state) == 0) continue; /* * We special case the first call to gss_init_sec_context so that * all token providers have the opportunity to generate an initial * context token. Providers where inputTokenType is ITOK_TYPE_NONE * are always called and generally act on state transition boundaries, * for example to advance the state after a series of optional tokens * (as is the case with the extension token exchange) or to generate * a new token after the state was advanced by a provider which did * not emit a token. */ if (smp->inputTokenType == ITOK_TYPE_NONE || initialContextToken) { processToken = 1; } else if ((smFlags & SM_FLAG_TRANSITED) == 0) { /* Don't regurgitate a token which belonds to a previous state. */ 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; *minor = GSSEAP_DUPLICATE_ITOK; break; } processToken = 1; innerInputToken = &inputTokens.buffers.elements[j]; inputTokenType = &inputTokens.types[j]; } } if (GSS_ERROR(major)) break; } if (processToken) { enum gss_eap_state oldState = ctx->state; smFlags = 0; if (inputTokenType != NULL && (*inputTokenType & ITOK_FLAG_CRITICAL)) smFlags |= SM_FLAG_INPUT_TOKEN_CRITICAL; major = smp->processToken(minor, cred, ctx, target, mech, reqFlags, timeReq, chanBindings, innerInputToken, &innerOutputToken, &smFlags); if (GSS_ERROR(major)) break; if (inputTokenType != NULL) *inputTokenType |= ITOK_FLAG_VERIFIED; if (ctx->state < oldState) i = 0; /* restart */ else if (ctx->state != oldState) smFlags |= SM_FLAG_TRANSITED; if (innerOutputToken.value != NULL) { 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) 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) || outputTokens.buffers.count != 0)) { SM_ASSERT_VALID(ctx, major); break; } } else if ((smp->itokFlags & SM_ITOK_FLAG_REQUIRED) && smp->inputTokenType != ITOK_TYPE_NONE) { /* Check for required inner tokens */ major = GSS_S_DEFECTIVE_TOKEN; *minor = GSSEAP_MISSING_REQUIRED_ITOK; break; } } GSSEAP_ASSERT(outputTokens.buffers.count <= smCount); /* Check we understood all critical tokens sent by peer */ if (!GSS_ERROR(major)) { 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; } } } /* Optionaly emit an error token if we are the acceptor */ if (GSS_ERROR(major)) { if (CTX_IS_INITIATOR(ctx)) goto cleanup; /* return error directly to caller */ /* replace any emitted tokens with error token */ gssEapReleaseInnerTokens(&tmpMinor, &outputTokens, 1); tmpMajor = makeErrorToken(&tmpMinor, major, *minor, &outputTokens); if (GSS_ERROR(tmpMajor)) { major = tmpMajor; *minor = tmpMinor; goto cleanup; } } /* Format output token from inner tokens */ 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, &outputTokens, &unwrappedOutputToken); if (tmpMajor == GSS_S_COMPLETE) { if (CTX_IS_INITIATOR(ctx)) tokType = TOK_TYPE_INITIATOR_CONTEXT; else tokType = TOK_TYPE_ACCEPTOR_CONTEXT; tmpMajor = gssEapMakeToken(&tmpMinor, ctx, &unwrappedOutputToken, tokType, outputToken); if (GSS_ERROR(tmpMajor)) { major = tmpMajor; *minor = tmpMinor; goto cleanup; } } } /* If the context is established, empty tokens only to be emitted by initiator */ GSSEAP_ASSERT(!CTX_IS_ESTABLISHED(ctx) || ((outputToken->length == 0) == CTX_IS_INITIATOR(ctx))); SM_ASSERT_VALID(ctx, major); cleanup: gssEapReleaseInnerTokens(&tmpMinor, &inputTokens, 0); gssEapReleaseInnerTokens(&tmpMinor, &inputTokens, 1); gss_release_buffer(&tmpMinor, &unwrappedOutputToken); ctx->inputTokens = NULL; ctx->outputTokens = NULL; return major; }
static OM_uint32 gssEapDuplicateCred(OM_uint32 *minor, const gss_cred_id_t src, gss_cred_id_t *pDst) { OM_uint32 major, tmpMinor; gss_cred_id_t dst = GSS_C_NO_CREDENTIAL; *pDst = GSS_C_NO_CREDENTIAL; major = gssEapAllocCred(minor, &dst); if (GSS_ERROR(major)) goto cleanup; dst->flags = src->flags; if (src->name != GSS_C_NO_NAME) { major = gssEapDuplicateName(minor, src->name, &dst->name); if (GSS_ERROR(major)) goto cleanup; } if (src->target != GSS_C_NO_NAME) { major = gssEapDuplicateName(minor, src->target, &dst->target); if (GSS_ERROR(major)) goto cleanup; } if (src->password.value != NULL) { major = duplicateBuffer(minor, &src->password, &dst->password); if (GSS_ERROR(major)) goto cleanup; } #ifndef MECH_EAP if (src->deleg_assertions.value != NULL) { major = duplicateBuffer(minor, &src->deleg_assertions, &dst->deleg_assertions); if (GSS_ERROR(major)) goto cleanup; } #endif major = duplicateOidSet(minor, src->mechanisms, &dst->mechanisms); if (GSS_ERROR(major)) goto cleanup; dst->expiryTime = src->expiryTime; if (src->radiusConfigFile.value != NULL) duplicateBufferOrCleanup(&src->radiusConfigFile, &dst->radiusConfigFile); if (src->radiusConfigStanza.value != NULL) duplicateBufferOrCleanup(&src->radiusConfigStanza, &dst->radiusConfigStanza); if (src->caCertificate.value != NULL) duplicateBufferOrCleanup(&src->caCertificate, &dst->caCertificate); if (src->subjectNameConstraint.value != NULL) duplicateBufferOrCleanup(&src->subjectNameConstraint, &dst->subjectNameConstraint); if (src->subjectAltNameConstraint.value != NULL) duplicateBufferOrCleanup(&src->subjectAltNameConstraint, &dst->subjectAltNameConstraint); *pDst = dst; dst = GSS_C_NO_CREDENTIAL; major = GSS_S_COMPLETE; *minor = 0; cleanup: gssEapReleaseCred(&tmpMinor, &dst); return major; }
static OM_uint32 readStaticIdentityFile(OM_uint32 *minor, gss_buffer_t defaultIdentity, gss_buffer_t defaultPassword) { OM_uint32 major, tmpMinor; FILE *fp = NULL; char buf[BUFSIZ]; char *ccacheName; int i = 0; #ifndef WIN32 struct passwd *pw = NULL, pwd; char pwbuf[BUFSIZ]; #endif defaultIdentity->length = 0; defaultIdentity->value = NULL; if (defaultPassword != GSS_C_NO_BUFFER) { defaultPassword->length = 0; defaultPassword->value = NULL; } ccacheName = getenv("GSSEAP_IDENTITY"); if (ccacheName == NULL) { #ifdef WIN32 TCHAR szPath[MAX_PATH]; if (!SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, /* |CSIDL_FLAG_CREATE */ NULL, /* User access token */ 0, /* SHGFP_TYPE_CURRENT */ szPath))) { major = GSS_S_CRED_UNAVAIL; *minor = GSSEAP_GET_LAST_ERROR(); /* XXX */ goto cleanup; } snprintf(buf, sizeof(buf), "%s/.gss_eap_id", szPath); #else if (getpwuid_r(getuid(), &pwd, pwbuf, sizeof(pwbuf), &pw) != 0 || pw == NULL || pw->pw_dir == NULL) { major = GSS_S_CRED_UNAVAIL; *minor = GSSEAP_GET_LAST_ERROR(); goto cleanup; } snprintf(buf, sizeof(buf), "%s/.gss_eap_id", pw->pw_dir); #endif /* WIN32 */ ccacheName = buf; } fp = fopen(ccacheName, "r"); if (fp == NULL) { major = GSS_S_CRED_UNAVAIL; *minor = GSSEAP_NO_DEFAULT_CRED; goto cleanup; } while (fgets(buf, sizeof(buf), fp) != NULL) { gss_buffer_desc src, *dst; src.length = strlen(buf); src.value = buf; if (src.length == 0) break; if (buf[src.length - 1] == '\n') { buf[src.length - 1] = '\0'; if (--src.length == 0) break; } if (i == 0) dst = defaultIdentity; else if (i == 1) dst = defaultPassword; else break; if (dst != GSS_C_NO_BUFFER) { major = duplicateBuffer(minor, &src, dst); if (GSS_ERROR(major)) goto cleanup; } i++; } if (defaultIdentity->length == 0) { major = GSS_S_CRED_UNAVAIL; *minor = GSSEAP_NO_DEFAULT_CRED; goto cleanup; } major = GSS_S_COMPLETE; *minor = 0; cleanup: if (fp != NULL) fclose(fp); if (GSS_ERROR(major)) { gss_release_buffer(&tmpMinor, defaultIdentity); zeroAndReleasePassword(defaultPassword); } memset(buf, 0, sizeof(buf)); return major; }