static OM_uint32 importKerberosKey(OM_uint32 *minor, unsigned char **pBuf, size_t *pRemain, krb5_cksumtype *checksumType, krb5_enctype *pEncryptionType, krb5_keyblock *pKey) { unsigned char *p = *pBuf; size_t remain = *pRemain; OM_uint32 encryptionType; OM_uint32 length; krb5_context krbContext; krb5_keyblock key; krb5_error_code code; GSSEAP_KRB_INIT(&krbContext); KRB_KEY_INIT(pKey); if (remain < 12) { *minor = GSSEAP_TOK_TRUNC; return GSS_S_DEFECTIVE_TOKEN; } *checksumType = load_uint32_be(&p[0]); encryptionType = load_uint32_be(&p[4]); length = load_uint32_be(&p[8]); if ((length != 0) != (encryptionType != ENCTYPE_NULL)) { *minor = GSSEAP_BAD_CONTEXT_TOKEN; return GSS_S_DEFECTIVE_TOKEN; } if (remain - 12 < length) { *minor = GSSEAP_TOK_TRUNC; return GSS_S_DEFECTIVE_TOKEN; } if (encryptionType != ENCTYPE_NULL) { KRB_KEY_INIT(&key); KRB_KEY_TYPE(&key) = encryptionType; KRB_KEY_LENGTH(&key) = length; KRB_KEY_DATA(&key) = &p[12]; code = krb5_copy_keyblock_contents(krbContext, &key, pKey); if (code != 0) { *minor = code; return GSS_S_FAILURE; } } *pBuf += 12 + length; *pRemain -= 12 + length; *pEncryptionType = encryptionType; *minor = 0; return GSS_S_COMPLETE; }
static OM_uint32 inquireSessionKey(OM_uint32 *minor, const gss_ctx_id_t ctx, const gss_OID desired_object GSSEAP_UNUSED, gss_buffer_set_t *dataSet) { OM_uint32 major; gss_buffer_desc buf; if (ctx->encryptionType == ENCTYPE_NULL) { major = GSS_S_UNAVAILABLE; *minor = GSSEAP_KEY_UNAVAILABLE; goto cleanup; } buf.length = KRB_KEY_LENGTH(&ctx->rfc3961Key); buf.value = KRB_KEY_DATA(&ctx->rfc3961Key); major = gss_add_buffer_set_member(minor, &buf, dataSet); if (GSS_ERROR(major)) goto cleanup; major = addEnctypeOidToBufferSet(minor, ctx->encryptionType, dataSet); if (GSS_ERROR(major)) goto cleanup; major = GSS_S_COMPLETE; *minor = 0; cleanup: if (GSS_ERROR(major)) zeroAndReleaseBufferSet(dataSet); return major; }
OM_uint32 gssEapExportSecContext(OM_uint32 *minor, gss_ctx_id_t ctx, gss_buffer_t token) { OM_uint32 major, tmpMinor; size_t length; gss_buffer_desc initiatorName = GSS_C_EMPTY_BUFFER; gss_buffer_desc acceptorName = GSS_C_EMPTY_BUFFER; gss_buffer_desc partialCtx = GSS_C_EMPTY_BUFFER; gss_buffer_desc key; unsigned char *p; if ((CTX_IS_INITIATOR(ctx) && !CTX_IS_ESTABLISHED(ctx)) || ctx->mechanismUsed == GSS_C_NO_OID) { *minor = GSSEAP_CONTEXT_INCOMPLETE; return GSS_S_NO_CONTEXT; } key.length = KRB_KEY_LENGTH(&ctx->rfc3961Key); key.value = KRB_KEY_DATA(&ctx->rfc3961Key); if (ctx->initiatorName != GSS_C_NO_NAME) { major = gssEapExportNameInternal(minor, ctx->initiatorName, &initiatorName, EXPORT_NAME_FLAG_COMPOSITE); if (GSS_ERROR(major)) goto cleanup; } if (ctx->acceptorName != GSS_C_NO_NAME) { major = gssEapExportNameInternal(minor, ctx->acceptorName, &acceptorName, EXPORT_NAME_FLAG_COMPOSITE); if (GSS_ERROR(major)) goto cleanup; } #ifdef GSSEAP_ENABLE_ACCEPTOR /* * The partial context is only transmitted for unestablished acceptor * contexts. */ if (!CTX_IS_INITIATOR(ctx) && !CTX_IS_ESTABLISHED(ctx) && (ctx->flags & CTX_FLAG_KRB_REAUTH) == 0) { major = gssEapExportPartialContext(minor, ctx, &partialCtx); if (GSS_ERROR(major)) goto cleanup; } #endif length = 16; /* version, state, flags, */ length += 4 + ctx->mechanismUsed->length; /* mechanismUsed */ length += 12 + key.length; /* rfc3961Key.value */ length += 4 + initiatorName.length; /* initiatorName.value */ length += 4 + acceptorName.length; /* acceptorName.value */ length += 24 + sequenceSize(ctx->seqState); /* seqState */ if (partialCtx.value != NULL) length += 4 + partialCtx.length; /* partialCtx.value */ token->value = GSSEAP_MALLOC(length); if (token->value == NULL) { major = GSS_S_FAILURE; *minor = ENOMEM; goto cleanup; } token->length = length; p = (unsigned char *)token->value; store_uint32_be(EAP_EXPORT_CONTEXT_V1, &p[0]); /* version */ store_uint32_be(GSSEAP_SM_STATE(ctx), &p[4]); store_uint32_be(ctx->flags, &p[8]); store_uint32_be(ctx->gssFlags, &p[12]); p = store_oid(ctx->mechanismUsed, &p[16]); store_uint32_be(ctx->checksumType, &p[0]); store_uint32_be(ctx->encryptionType, &p[4]); p = store_buffer(&key, &p[8], FALSE); p = store_buffer(&initiatorName, p, FALSE); p = store_buffer(&acceptorName, p, FALSE); store_uint64_be(ctx->expiryTime, &p[0]); store_uint64_be(ctx->sendSeq, &p[8]); store_uint64_be(ctx->recvSeq, &p[16]); p += 24; major = sequenceExternalize(minor, ctx->seqState, &p, &length); if (GSS_ERROR(major)) goto cleanup; if (partialCtx.value != NULL) p = store_buffer(&partialCtx, p, FALSE); GSSEAP_ASSERT(p == (unsigned char *)token->value + token->length); major = GSS_S_COMPLETE; *minor = 0; cleanup: if (GSS_ERROR(major)) gss_release_buffer(&tmpMinor, token); gss_release_buffer(&tmpMinor, &initiatorName); gss_release_buffer(&tmpMinor, &acceptorName); gss_release_buffer(&tmpMinor, &partialCtx); return major; }