#include "gssapiP_eap.h"
+static OM_uint32
+acceptReadyCommon(OM_uint32 *minor, gss_ctx_id_t ctx, gss_cred_id_t cred)
+{
+ OM_uint32 major;
+
+ major = sequenceInit(minor,
+ &ctx->seqState, ctx->recvSeq,
+ ((ctx->gssFlags & GSS_C_REPLAY_FLAG) != 0),
+ ((ctx->gssFlags & GSS_C_SEQUENCE_FLAG) != 0),
+ TRUE);
+ if (GSS_ERROR(major))
+ return major;
+
+ return GSS_S_COMPLETE;
+}
+
+
/*
* Mark a context as ready for cryptographic operations
*/
static OM_uint32
-acceptReady(OM_uint32 *minor, gss_ctx_id_t ctx, gss_cred_id_t cred)
+acceptReadyEap(OM_uint32 *minor, gss_ctx_id_t ctx, gss_cred_id_t cred)
{
OM_uint32 major, tmpMinor;
VALUE_PAIR *vp;
ctx->encryptionType = ENCTYPE_NULL;
}
- major = sequenceInit(minor,
- &ctx->seqState, ctx->recvSeq,
- ((ctx->gssFlags & GSS_C_REPLAY_FLAG) != 0),
- ((ctx->gssFlags & GSS_C_SEQUENCE_FLAG) != 0),
- TRUE);
- if (GSS_ERROR(major))
- return major;
-
- return GSS_S_COMPLETE;
+ return acceptReadyCommon(minor, ctx, cred);
}
static OM_uint32
ctx->acceptorCtx.avps = received;
received = NULL;
- major = acceptReady(minor, ctx, cred);
+ major = acceptReadyEap(minor, ctx, cred);
if (GSS_ERROR(major))
goto cleanup;
outputToken->length = 0;
outputToken->value = NULL;
- if (chanBindings == GSS_C_NO_CHANNEL_BINDINGS) {
- ctx->state = EAP_STATE_ESTABLISHED;
- return GSS_S_COMPLETE;
- }
-
- if (inputToken->length < 14) {
- return GSS_S_DEFECTIVE_TOKEN;
- }
+ if (chanBindings != GSS_C_NO_CHANNEL_BINDINGS) {
+ if (inputToken->length < 14) {
+ return GSS_S_DEFECTIVE_TOKEN;
+ }
- iov[0].type = GSS_IOV_BUFFER_TYPE_DATA;
- iov[0].buffer.length = 0;
- iov[0].buffer.value = NULL;
+ iov[0].type = GSS_IOV_BUFFER_TYPE_DATA;
+ iov[0].buffer.length = 0;
+ iov[0].buffer.value = NULL;
- if (chanBindings != GSS_C_NO_CHANNEL_BINDINGS)
- iov[0].buffer = chanBindings->application_data;
+ if (chanBindings != GSS_C_NO_CHANNEL_BINDINGS)
+ iov[0].buffer = chanBindings->application_data;
- iov[1].type = GSS_IOV_BUFFER_TYPE_HEADER;
- iov[1].buffer.length = 16;
- iov[1].buffer.value = (unsigned char *)inputToken->value - 2;
+ iov[1].type = GSS_IOV_BUFFER_TYPE_HEADER;
+ iov[1].buffer.length = 16;
+ iov[1].buffer.value = (unsigned char *)inputToken->value - 2;
- assert(load_uint16_be(iov[1].buffer.value) == TOK_TYPE_GSS_CB);
+ assert(load_uint16_be(iov[1].buffer.value) == TOK_TYPE_GSS_CB);
- iov[2].type = GSS_IOV_BUFFER_TYPE_TRAILER;
- iov[2].buffer.length = inputToken->length - 14;
- iov[2].buffer.value = (unsigned char *)inputToken->value + 14;
+ iov[2].type = GSS_IOV_BUFFER_TYPE_TRAILER;
+ iov[2].buffer.length = inputToken->length - 14;
+ iov[2].buffer.value = (unsigned char *)inputToken->value + 14;
- major = gssEapUnwrapOrVerifyMIC(minor, ctx, NULL, NULL,
- iov, 3, TOK_TYPE_GSS_CB);
- if (major == GSS_S_COMPLETE) {
- ctx->state = EAP_STATE_ESTABLISHED;
+ major = gssEapUnwrapOrVerifyMIC(minor, ctx, NULL, NULL,
+ iov, 3, TOK_TYPE_GSS_CB);
+ if (GSS_ERROR(major))
+ return major;
}
-#if 0
- gss_release_buffer(&tmpMinor, &iov[0].buffer);
-#endif
-
- return major;
+ ctx->state = EAP_STATE_KRB_REAUTH_CRED;
+ return GSS_S_CONTINUE_NEEDED;
}
static OM_uint32
-eapGssSmAcceptKrbCred(OM_uint32 *minor,
- gss_ctx_id_t ctx,
- gss_cred_id_t cred,
- gss_buffer_t inputToken,
- gss_channel_bindings_t chanBindings,
- gss_buffer_t outputToken)
+eapGssSmAcceptKrbReauthCred(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_cred_id_t cred,
+ gss_buffer_t inputToken,
+ gss_channel_bindings_t chanBindings,
+ gss_buffer_t outputToken)
{
- /* Called with already established context */
- *minor = EINVAL;
- return GSS_S_BAD_STATUS;
+ OM_uint32 major;
+
+ major = gssEapMakeReauthCreds(minor, ctx, cred, outputToken);
+ if (GSS_ERROR(major))
+ return major;
+
+ ctx->state = EAP_STATE_ESTABLISHED;
+
+ return GSS_S_COMPLETE;
}
static OM_uint32
return GSS_S_BAD_STATUS;
}
+static OM_uint32
+acceptReadyKrb(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_cred_id_t cred,
+ const gss_name_t initiator,
+ const gss_OID mech,
+ OM_uint32 timeRec)
+{
+ OM_uint32 major, tmpMinor;
+ gss_buffer_set_t keyData = GSS_C_NO_BUFFER_SET;
+ gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
+
+ if (!oidEqual(mech, gss_mech_krb5)) {
+ major = GSS_S_BAD_MECH;
+ goto cleanup;
+ }
+
+ major = gssInquireSecContextByOid(minor, ctx->kerberosCtx,
+ GSS_C_INQ_SSPI_SESSION_KEY, &keyData);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ {
+ gss_OID_desc oid;
+ int suffix;
+
+ oid.length = keyData->elements[1].length;
+ oid.elements = keyData->elements[1].value;
+
+ /* GSS_KRB5_SESSION_KEY_ENCTYPE_OID */
+ major = decomposeOid(minor,
+ "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x04",
+ 10, &oid, &suffix);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ ctx->encryptionType = suffix;
+ }
+
+ {
+ krb5_context krbContext = NULL;
+ krb5_keyblock key;
+
+ GSSEAP_KRB_INIT(&krbContext);
+
+ KRB_KEY_LENGTH(&key) = keyData->elements[0].length;
+ KRB_KEY_DATA(&key) = keyData->elements[0].value;
+ KRB_KEY_TYPE(&key) = ctx->encryptionType;
+
+ *minor = krb5_copy_keyblock_contents(krbContext,
+ &key, &ctx->rfc3961Key);
+ if (*minor != 0) {
+ major = GSS_S_FAILURE;
+ goto cleanup;
+ }
+ }
+
+ major = rfc3961ChecksumTypeForKey(minor, &ctx->rfc3961Key,
+ &ctx->checksumType);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ major = gssDisplayName(minor, initiator, &nameBuf, NULL);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ major = gssEapImportName(minor, &nameBuf, GSS_C_NT_USER_NAME,
+ &ctx->initiatorName);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ if (cred != GSS_C_NO_CREDENTIAL && cred->name != GSS_C_NO_NAME) {
+ major = gssEapDuplicateName(minor, cred->name, &ctx->acceptorName);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+ if (timeRec != GSS_C_INDEFINITE)
+ ctx->expiryTime = time(NULL) + timeRec;
+
+ major = acceptReadyCommon(minor, ctx, cred);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ ctx->state = EAP_STATE_ESTABLISHED;
+ ctx->mechanismUsed = GSS_EAP_MECHANISM;
+
+cleanup:
+ gss_release_buffer_set(&tmpMinor, &keyData);
+ gss_release_buffer(&tmpMinor, &nameBuf);
+
+ return major;
+}
+
+static OM_uint32
+eapGssSmAcceptGssReauth(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_cred_id_t cred,
+ gss_buffer_t inputToken,
+ gss_channel_bindings_t chanBindings,
+ gss_buffer_t outputToken)
+{
+ OM_uint32 major, tmpMinor;
+ gss_cred_id_t krbCred = GSS_C_NO_CREDENTIAL;
+ gss_name_t krbInitiator = GSS_C_NO_NAME;
+ gss_OID mech = GSS_C_NO_OID;
+ OM_uint32 timeRec = GSS_C_INDEFINITE;
+
+ ctx->flags |= CTX_FLAG_KRB_REAUTH_GSS;
+
+ if (cred != GSS_C_NO_CREDENTIAL)
+ krbCred = cred->krbCred;
+
+ major = gssAcceptSecContext(minor,
+ &ctx->kerberosCtx,
+ krbCred,
+ inputToken,
+ chanBindings,
+ &krbInitiator,
+ &mech,
+ outputToken,
+ &ctx->gssFlags,
+ &timeRec,
+ NULL);
+ if (major == GSS_S_COMPLETE) {
+ major = acceptReadyKrb(minor, ctx, cred,
+ krbInitiator, mech, timeRec);
+ }
+
+ gssReleaseName(&tmpMinor, &krbInitiator);
+
+ return major;
+}
+
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_GSS_CB, TOK_TYPE_NONE, eapGssSmAcceptGssChannelBindings },
- { TOK_TYPE_NONE, TOK_TYPE_KRB_CRED, eapGssSmAcceptKrbCred },
- { 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_GSS_CB, TOK_TYPE_NONE, eapGssSmAcceptGssChannelBindings },
+ { TOK_TYPE_NONE, TOK_TYPE_KRB_CRED, eapGssSmAcceptKrbReauthCred },
+ { TOK_TYPE_NONE, TOK_TYPE_NONE, eapGssSmAcceptEstablished },
+ { TOK_TYPE_GSS_REAUTH, TOK_TYPE_GSS_REAUTH, eapGssSmAcceptGssReauth },
};
OM_uint32
struct gss_eap_acceptor_sm *sm = NULL;
gss_buffer_desc innerInputToken = GSS_C_EMPTY_BUFFER;
gss_buffer_desc innerOutputToken = GSS_C_EMPTY_BUFFER;
+ enum gss_eap_token_type tokType;
*minor = 0;
sm = &eapGssAcceptorSm[ctx->state];
major = gssEapVerifyToken(minor, ctx, input_token,
- sm->inputTokenType, &innerInputToken);
- if (GSS_ERROR(major))
+ sm->inputTokenType, &tokType,
+ &innerInputToken);
+ if (major == GSS_S_DEFECTIVE_TOKEN && tokType == TOK_TYPE_GSS_REAUTH) {
+ ctx->state = EAP_STATE_KRB_REAUTH_GSS;
+ } else if (GSS_ERROR(major)) {
goto cleanup;
+ }
/* If credentials were provided, check they're usable with this mech */
if (!gssEapCredAvailable(cred, ctx->mechanismUsed)) {
major = gssEapLocalAttrProviderInit(&minor);
assert(major == GSS_S_COMPLETE);
+
+ major = gssEapReauthInitialize(&minor);
+ assert(major == GSS_S_COMPLETE);
}
static void
/* GSS includes */
#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_krb5.h>
#include <gssapi/gssapi_ext.h>
#include "gssapi_eap.h"
};
#define CTX_FLAG_INITIATOR 0x00000001
+#define CTX_FLAG_KRB_REAUTH_GSS 0x00000002
#define CTX_IS_INITIATOR(ctx) (((ctx)->flags & CTX_FLAG_INITIATOR) != 0)
EAP_STATE_IDENTITY = 0,
EAP_STATE_AUTHENTICATE,
EAP_STATE_GSS_CHANNEL_BINDINGS,
- EAP_STATE_FAST_REAUTH,
- EAP_STATE_ESTABLISHED
+ EAP_STATE_KRB_REAUTH_CRED,
+ EAP_STATE_ESTABLISHED,
+ EAP_STATE_KRB_REAUTH_GSS
};
#define CTX_IS_ESTABLISHED(ctx) ((ctx)->state == EAP_STATE_ESTABLISHED)
#define initiatorCtx ctxU.initiator
struct gss_eap_acceptor_ctx acceptor;
#define acceptorCtx ctxU.acceptor
+ gss_ctx_id_t kerberos;
+ #define kerberosCtx ctxU.kerberos
} ctxU;
};
if (GSS_ERROR(major))
goto cleanup;
- major = GSS_S_COMPLETE;
- ctx->state = EAP_STATE_ESTABLISHED;
+ major = GSS_S_CONTINUE_NEEDED;
+ ctx->state = EAP_STATE_KRB_REAUTH_CRED;
cleanup:
gssEapReleaseIov(iov, 2);
}
static OM_uint32
-eapGssSmInitKrbCred(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)
+eapGssSmInitKrbReauthCred(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)
{
- /* Called with already established context */
- *minor = EINVAL;
- return GSS_S_BAD_STATUS;
+ OM_uint32 major;
+
+ major = gssEapStoreReauthCreds(minor, ctx, cred, inputToken);
+ if (GSS_ERROR(major))
+ return major;
+
+ ctx->state = EAP_STATE_ESTABLISHED;
+
+ return GSS_S_COMPLETE;
}
static OM_uint32
{ TOK_TYPE_NONE, TOK_TYPE_EAP_RESP, eapGssSmInitIdentity },
{ TOK_TYPE_EAP_REQ, TOK_TYPE_EAP_RESP, eapGssSmInitAuthenticate },
{ TOK_TYPE_NONE, TOK_TYPE_GSS_CB, eapGssSmInitGssChannelBindings },
- { TOK_TYPE_KRB_CRED,TOK_TYPE_NONE, eapGssSmInitKrbCred },
+ { TOK_TYPE_KRB_CRED,TOK_TYPE_NONE, eapGssSmInitKrbReauthCred },
{ TOK_TYPE_NONE, TOK_TYPE_NONE, eapGssSmInitEstablished },
};
struct gss_eap_initiator_sm *sm = NULL;
gss_buffer_desc innerInputToken;
gss_buffer_desc innerOutputToken = GSS_C_EMPTY_BUFFER;
+ enum gss_eap_token_type tokType;
*minor = 0;
if (input_token != GSS_C_NO_BUFFER) {
major = gssEapVerifyToken(minor, ctx, input_token,
- sm->inputTokenType, &innerInputToken);
+ sm->inputTokenType,
+ &tokType, &innerInputToken);
if (GSS_ERROR(major))
goto cleanup;
} else {
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);
OM_uint32
size_t *body_size,
unsigned char **buf_in,
size_t toksize_in,
- enum gss_eap_token_type tok_type);
+ enum gss_eap_token_type tok_type,
+ enum gss_eap_token_type *ret_tok_type);
/* Helper macros */
#define GSSEAP_CALLOC(count, size) (calloc((count), (size)))
#endif
#include "util_attr.h"
+#include "util_reauth.h"
#endif /* _UTIL_H_ */
gssEapKerberosInit(&tmpMinor, &krbContext);
- if (CTX_IS_INITIATOR(ctx)) {
+ if (ctx->flags & CTX_FLAG_KRB_REAUTH_GSS) {
+ gssDeleteSecContext(&tmpMinor, &ctx->kerberosCtx, GSS_C_NO_BUFFER);
+ } else if (CTX_IS_INITIATOR(ctx)) {
releaseInitiatorContext(&ctx->initiatorCtx);
} else {
releaseAcceptorContext(&ctx->acceptorCtx);
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)
{
OM_uint32 major;
}
major = verifyTokenHeader(minor, oid, &bodySize, &p,
- inputToken->length, tokenType);
+ inputToken->length, tokenType,
+ actualToken);
if (GSS_ERROR(major))
return GSS_S_DEFECTIVE_TOKEN;
if (cred->krbCredCache != NULL)
krb5_cc_destroy(krbContext, cred->krbCredCache);
+ if (cred->krbCred != GSS_C_NO_CREDENTIAL)
+ gssReleaseCred(&tmpMinor, &cred->krbCred);
GSSEAP_MUTEX_DESTROY(&cred->mutex);
memset(cred, 0, sizeof(*cred));
#include "gssapiP_eap.h"
+#include <dlfcn.h>
+
/*
* Fast reauthentication support for EAP GSS.
*/
#define KRB5_AUTHDATA_RADIUS_AVP 513
+krb5_error_code
+krb5_encrypt_tkt_part(krb5_context, const krb5_keyblock *, krb5_ticket *);
+
+krb5_error_code
+encode_krb5_ticket(const krb5_ticket *rep, krb5_data **code);
+
static krb5_error_code
getAcceptorKey(krb5_context krbContext,
gss_ctx_id_t ctx,
while ((code = krb5_kt_next_entry(krbContext, keytab,
&ktent, &cursor)) == 0) {
- if (ktent.key.enctype != ctx->encryptionType) {
+ if (ktent.key.enctype == ctx->encryptionType) {
+ break;
+ } else {
krb5_free_keytab_entry_contents(krbContext, &ktent);
- continue;
}
}
}
- code = krb5_copy_principal(krbContext, ktent.principal, princ);
- if (code != 0)
- goto cleanup;
-
- code = krb5_copy_keyblock_contents(krbContext, &ktent.key, key);
- if (code != 0)
- goto cleanup;
+ if (code == 0) {
+ *princ = ktent.principal;
+ *key = ktent.key;
+ }
cleanup:
if (cred == GSS_C_NO_CREDENTIAL || cred->name == GSS_C_NO_NAME)
krb5_kt_end_seq_get(krbContext, keytab, &cursor);
-
- krb5_free_keytab_entry_contents(krbContext, &ktent);
- krb5_kt_end_seq_get(krbContext, keytab, &cursor);
krb5_kt_close(krbContext, keytab);
if (code != 0) {
return code;
}
-static OM_uint32
-makeReauthCreds(OM_uint32 *minor,
- gss_ctx_id_t ctx,
- gss_cred_id_t cred,
- gss_buffer_t credBuf)
+OM_uint32
+gssEapMakeReauthCreds(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_cred_id_t cred,
+ gss_buffer_t credBuf)
{
OM_uint32 major = GSS_S_COMPLETE, code;
krb5_context krbContext = NULL;
if (code != 0)
goto cleanup;
+ code = krb5_encrypt_tkt_part(krbContext, &acceptorKey, &ticket);
+ if (code != 0)
+ goto cleanup;
+
creds.client = enc_part.client;
creds.server = ticket.server;
creds.keyblock = session;
if (code != 0)
goto cleanup;
+ code = krb5_auth_con_setflags(krbContext, authContext, 0);
+ if (code != 0)
+ goto cleanup;
+
code = krb5_auth_con_setsendsubkey(krbContext, authContext, &ctx->rfc3961Key);
if (code != 0)
goto cleanup;
krbDataToGssBuffer(credsData, credBuf);
- code = krb5_encrypt_tkt_part(krbContext, acceptorKey, &ticket);
- if (code != 0)
- goto cleanup;
-
cleanup:
*minor = code;
return major;
}
-static OM_uint32
-storeReauthCreds(OM_uint32 *minor,
- gss_ctx_id_t ctx,
- gss_cred_id_t cred,
- gss_buffer_t credBuf)
+OM_uint32
+gssEapStoreReauthCreds(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_cred_id_t cred,
+ gss_buffer_t credBuf)
{
OM_uint32 major = GSS_S_COMPLETE, code;
krb5_context krbContext = NULL;
if (code != 0)
goto cleanup;
+ code = krb5_auth_con_setflags(krbContext, authContext, 0);
+ if (code != 0)
+ goto cleanup;
+
code = krb5_auth_con_setrecvsubkey(krbContext, authContext,
&ctx->rfc3961Key);
if (code != 0)
if (code != 0)
goto cleanup;
+ if (creds == NULL || creds[0] == NULL)
+ goto cleanup;
+ code = krb5_cc_new_unique(krbContext, "MEMORY", NULL, &cred->krbCredCache);
+ if (code != 0)
+ goto cleanup;
-/*
-OM_uint32 KRB5_CALLCONV
-gss_krb5_import_cred(OM_uint32 *minor_status,
- krb5_ccache id,
- krb5_principal keytab_principal,
- krb5_keytab keytab,
- gss_cred_id_t *cred);
-*/
+ code = krb5_cc_store_cred(krbContext, cred->krbCredCache, creds[0]);
+ if (code != 0)
+ goto cleanup;
- if (creds != NULL && creds[0] != NULL) {
- }
+ major = gss_krb5_import_cred(minor, cred->krbCredCache, NULL, NULL, &cred->krbCred);
+ if (GSS_ERROR(major))
+ goto cleanup;
cleanup:
*minor = code;
return major;
}
+
+static OM_uint32 (*gssInitSecContextNext)(
+ OM_uint32 *minor,
+ gss_cred_id_t cred,
+ gss_ctx_id_t *context_handle,
+ gss_name_t target_name,
+ gss_OID mech_type,
+ OM_uint32 req_flags,
+ OM_uint32 time_req,
+ gss_channel_bindings_t input_chan_bindings,
+ gss_buffer_t input_token,
+ gss_OID *actual_mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec);
+
+static OM_uint32 (*gssAcceptSecContextNext)(
+ OM_uint32 *minor,
+ gss_ctx_id_t *context_handle,
+ gss_cred_id_t cred,
+ gss_buffer_t input_token,
+ gss_channel_bindings_t input_chan_bindings,
+ gss_name_t *src_name,
+ gss_OID *mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec,
+ gss_cred_id_t *delegated_cred_handle);
+
+static OM_uint32 (*gssReleaseCredNext)(
+ OM_uint32 *minor,
+ gss_cred_id_t *cred_handle);
+
+static OM_uint32 (*gssReleaseNameNext)(
+ OM_uint32 *minor,
+ gss_name_t *name);
+
+static OM_uint32 (*gssInquireSecContextByOidNext)(
+ OM_uint32 *minor,
+ const gss_ctx_id_t context_handle,
+ const gss_OID desired_object,
+ gss_buffer_set_t *data_set);
+
+static OM_uint32 (*gssDeleteSecContextNext)(
+ OM_uint32 *minor,
+ gss_ctx_id_t *context_handle,
+ gss_buffer_t output_token);
+
+static OM_uint32 (*gssDisplayNameNext)(
+ OM_uint32 *minor,
+ gss_name_t name,
+ gss_buffer_t output_name_buffer,
+ gss_OID *output_name_type);
+
+OM_uint32
+gssEapReauthInitialize(OM_uint32 *minor)
+{
+ gssInitSecContextNext = dlsym(RTLD_NEXT, "gss_init_sec_context");
+ gssAcceptSecContextNext = dlsym(RTLD_NEXT, "gss_accept_sec_context");
+ gssReleaseCredNext = dlsym(RTLD_NEXT, "gss_release_cred");
+ gssReleaseNameNext = dlsym(RTLD_NEXT, "gss_release_name");
+ gssInquireSecContextByOidNext = dlsym(RTLD_NEXT, "gss_inquire_sec_context_by_oid");
+ gssDeleteSecContextNext = dlsym(RTLD_NEXT, "gss_delete_sec_context");
+
+ return GSS_S_COMPLETE;
+}
+
+OM_uint32
+gssInitSecContext(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ gss_ctx_id_t *context_handle,
+ gss_name_t target_name,
+ gss_OID mech_type,
+ OM_uint32 req_flags,
+ OM_uint32 time_req,
+ gss_channel_bindings_t input_chan_bindings,
+ gss_buffer_t input_token,
+ gss_OID *actual_mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec)
+{
+ if (gssInitSecContextNext == NULL)
+ return GSS_S_UNAVAILABLE;
+
+ return gssInitSecContextNext(minor, cred, context_handle,
+ target_name, mech_type, req_flags,
+ time_req, input_chan_bindings,
+ input_token, actual_mech_type,
+ output_token, ret_flags, time_rec);
+}
+
+OM_uint32
+gssAcceptSecContext(OM_uint32 *minor,
+ gss_ctx_id_t *context_handle,
+ gss_cred_id_t cred,
+ gss_buffer_t input_token,
+ gss_channel_bindings_t input_chan_bindings,
+ gss_name_t *src_name,
+ gss_OID *mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec,
+ gss_cred_id_t *delegated_cred_handle)
+{
+ if (gssAcceptSecContextNext == NULL)
+ return GSS_S_UNAVAILABLE;
+
+ return gssAcceptSecContextNext(minor, context_handle, cred,
+ input_token, input_chan_bindings,
+ src_name, mech_type, output_token,
+ ret_flags, time_rec, delegated_cred_handle);
+}
+
+OM_uint32
+gssReleaseCred(OM_uint32 *minor,
+ gss_cred_id_t *cred_handle)
+{
+ if (gssReleaseCredNext == NULL)
+ return GSS_S_UNAVAILABLE;
+
+ return gssReleaseCredNext(minor, cred_handle);
+}
+
+OM_uint32
+gssReleaseName(OM_uint32 *minor,
+ gss_name_t *name)
+{
+ if (gssReleaseName == NULL)
+ return GSS_S_UNAVAILABLE;
+
+ return gssReleaseNameNext(minor, name);
+}
+
+OM_uint32
+gssDeleteSecContext(OM_uint32 *minor,
+ gss_ctx_id_t *context_handle,
+ gss_buffer_t output_token)
+{
+ if (gssDeleteSecContextNext == NULL)
+ return GSS_S_UNAVAILABLE;
+
+ return gssDeleteSecContextNext(minor, context_handle, output_token);
+}
+
+OM_uint32
+gssDisplayName(OM_uint32 *minor,
+ gss_name_t name,
+ gss_buffer_t buffer,
+ gss_OID *name_type)
+{
+ if (gssDisplayNameNext == NULL)
+ return GSS_S_UNAVAILABLE;
+
+ return gssDisplayNameNext(minor, name, buffer, name_type);
+}
+
+OM_uint32
+gssInquireSecContextByOid(OM_uint32 *minor,
+ const gss_ctx_id_t context_handle,
+ const gss_OID desired_object,
+ gss_buffer_set_t *data_set)
+{
+ if (gssInquireSecContextByOidNext == NULL)
+ return GSS_S_UNAVAILABLE;
+
+ return gssInquireSecContextByOidNext(minor, context_handle,
+ desired_object, data_set);
+}
--- /dev/null
+/*
+ * Copyright (c) 2010, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "gssapiP_eap.h"
+
+#ifndef _UTIL_REAUTH_H_
+#define _UTIL_REAUTH_H_ 1
+
+OM_uint32
+gssInitSecContext(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ gss_ctx_id_t *context_handle,
+ gss_name_t target_name,
+ gss_OID mech_type,
+ OM_uint32 req_flags,
+ OM_uint32 time_req,
+ gss_channel_bindings_t input_chan_bindings,
+ gss_buffer_t input_token,
+ gss_OID *actual_mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec);
+
+OM_uint32
+gssAcceptSecContext(OM_uint32 *minor,
+ gss_ctx_id_t *context_handle,
+ gss_cred_id_t cred,
+ gss_buffer_t input_token,
+ gss_channel_bindings_t input_chan_bindings,
+ gss_name_t *src_name,
+ gss_OID *mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec,
+ gss_cred_id_t *delegated_cred_handle);
+
+OM_uint32
+gssReleaseCred(OM_uint32 *minor,
+ gss_cred_id_t *cred_handle);
+
+OM_uint32
+gssReleaseName(OM_uint32 *minor,
+ gss_name_t *name);
+
+OM_uint32
+gssDeleteSecContext(OM_uint32 *minor,
+ gss_ctx_id_t *context_handle,
+ gss_buffer_t output_token);
+
+OM_uint32
+gssDisplayName(OM_uint32 *minor,
+ gss_name_t name,
+ gss_buffer_t buffer,
+ gss_OID *name_type);
+
+OM_uint32
+gssInquireSecContextByOid(OM_uint32 *minor,
+ const gss_ctx_id_t context_handle,
+ const gss_OID desired_object,
+ gss_buffer_set_t *data_set);
+
+OM_uint32
+gssEapMakeReauthCreds(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_cred_id_t cred,
+ gss_buffer_t credBuf);
+
+OM_uint32
+gssEapStoreReauthCreds(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_cred_id_t cred,
+ gss_buffer_t credBuf);
+
+#endif /* _UTIL_REAUTH_H_ */
size_t *body_size,
unsigned char **buf_in,
size_t toksize_in,
- enum gss_eap_token_type tok_type)
+ enum gss_eap_token_type tok_type,
+ enum gss_eap_token_type *ret_tok_type)
{
unsigned char *buf = *buf_in;
ssize_t seqsize;
if ((toksize -= 2) < 0)
return GSS_S_DEFECTIVE_TOKEN;
- if ((*buf++ != ((tok_type >> 8) & 0xff)) ||
- (*buf++ != (tok_type & 0xff)))
+ *ret_tok_type = load_uint16_be(*buf);
+ if (tok_type != *ret_tok_type)
return GSS_S_DEFECTIVE_TOKEN;
+ *buf += 2;
}
*buf_in = buf;
*body_size = toksize;