#endif
static OM_uint32
-serverDeriveKey(OM_uint32 *minor,
- gss_ctx_id_t ctx)
+completeAccept(OM_uint32 *minor, gss_ctx_id_t ctx)
{
OM_uint32 major;
krb5_context krbContext;
ctx->gssFlags &= ~(GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
}
+ sequenceInit(&ctx->seqState, ctx->recvSeq,
+ ((ctx->gssFlags & GSS_C_REPLAY_FLAG) != 0),
+ ((ctx->gssFlags & GSS_C_SEQUENCE_FLAG) != 0),
+ TRUE);
+
return GSS_S_COMPLETE;
}
gss_channel_bindings_t chanBindings,
gss_buffer_t outputToken)
{
- OM_uint32 major, tmpMinor, tmpMajor;
+ OM_uint32 major;
+ OM_uint32 tmpMinor, tmpMajor;
int code;
struct wpabuf respData;
- struct eap_config *config = (struct eap_config *)&ctx->acceptorCtx.eapConfig;
static struct eapol_callbacks cb = { serverGetEapUser, serverGetEapReqIdText };
- wpabuf_set(&respData, inputToken->value, inputToken->length);
- ctx->acceptorCtx.eapPolInterface->eapRespData = &respData;
- ctx->acceptorCtx.eapPolInterface->eapResp = TRUE;
-
if (ctx->acceptorCtx.eap == NULL) {
- /* initial context token */
- config->eap_server = 1;
- config->ssl_ctx = ctx->acceptorCtx.tlsContext;
+ struct eap_config eapConfig;
major = initTls(minor, ctx);
if (GSS_ERROR(major))
goto cleanup;
- ctx->acceptorCtx.eap = eap_server_sm_init(ctx, &cb, config);
+ memset(&eapConfig, 0, sizeof(eapConfig));
+ eapConfig.eap_server = 1;
+ eapConfig.ssl_ctx = ctx->acceptorCtx.tlsContext;
+
+ ctx->acceptorCtx.eap = eap_server_sm_init(ctx, &cb, &eapConfig);
if (ctx->acceptorCtx.eap == NULL) {
major = GSS_S_FAILURE;
goto cleanup;
ctx->acceptorCtx.eapPolInterface->eapRestart = TRUE;
}
- if (ctx->acceptorName == GSS_C_NO_NAME && cred->name != GSS_C_NO_NAME) {
+ if (ctx->acceptorName == GSS_C_NO_NAME &&
+ cred != GSS_C_NO_CREDENTIAL &&
+ cred->name != GSS_C_NO_NAME) {
major = gss_duplicate_name(minor, cred->name, &ctx->acceptorName);
if (GSS_ERROR(major))
goto cleanup;
}
+ wpabuf_set(&respData, inputToken->value, inputToken->length);
+ ctx->acceptorCtx.eapPolInterface->eapRespData = &respData;
+ ctx->acceptorCtx.eapPolInterface->eapResp = TRUE;
+
code = eap_server_sm_step(ctx->acceptorCtx.eap);
if (ctx->acceptorCtx.eapPolInterface->eapReq) {
}
if (ctx->acceptorCtx.eapPolInterface->eapSuccess) {
- major = serverDeriveKey(minor, ctx);
- if (GSS_ERROR(major))
- goto cleanup;
-
ctx->acceptorCtx.eapPolInterface->eapSuccess = 0;
ctx->state = EAP_STATE_ESTABLISHED;
- major = GSS_S_COMPLETE;
+ major = completeAccept(minor, ctx);
} else if (ctx->acceptorCtx.eapPolInterface->eapFail) {
ctx->acceptorCtx.eapPolInterface->eapFail = 0;
major = GSS_S_FAILURE;
tmpMajor = duplicateBuffer(&tmpMinor, &buf, outputToken);
if (GSS_ERROR(tmpMajor)) {
major = tmpMajor;
+ *minor = tmpMinor;
goto cleanup;
}
}
cleanup:
+ ctx->acceptorCtx.eapPolInterface->eapRespData = NULL;
+
return major;
}
OM_uint32 *time_rec,
gss_cred_id_t *delegated_cred_handle)
{
- OM_uint32 major, tmpMinor;
+ OM_uint32 major;
+ OM_uint32 tmpMajor, tmpMinor;
gss_ctx_id_t ctx = *context_handle;
struct eap_gss_acceptor_sm *sm = NULL;
gss_buffer_desc innerInputToken, innerOutputToken;
goto cleanup;
} while (major == GSS_S_CONTINUE_NEEDED && innerOutputToken.length == 0);
- if (src_name != NULL && ctx->initiatorName != GSS_C_NO_NAME) {
- major = gss_duplicate_name(minor, ctx->initiatorName, src_name);
- if (GSS_ERROR(major))
- goto cleanup;
- }
if (mech_type != NULL) {
if (!gssEapInternalizeOid(ctx->mechanismUsed, mech_type))
duplicateOid(&tmpMinor, ctx->mechanismUsed, mech_type);
}
if (innerOutputToken.length != 0) {
- major = gssEapMakeToken(minor, ctx, &innerOutputToken,
- sm->outputTokenType, output_token);
- if (GSS_ERROR(major))
+ tmpMajor = gssEapMakeToken(&tmpMinor, ctx, &innerOutputToken,
+ sm->outputTokenType, output_token);
+ if (GSS_ERROR(tmpMajor)) {
+ major = tmpMajor;
+ *minor = tmpMinor;
goto cleanup;
+ }
}
if (ret_flags != NULL)
*ret_flags = ctx->gssFlags;
- if (time_rec != NULL)
- gss_context_time(&tmpMinor, ctx, time_rec);
if (delegated_cred_handle != NULL)
*delegated_cred_handle = GSS_C_NO_CREDENTIAL;
+ if (major == GSS_S_COMPLETE) {
+ if (src_name != NULL && ctx->initiatorName != GSS_C_NO_NAME) {
+ major = gss_duplicate_name(&tmpMinor, ctx->initiatorName, src_name);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+ if (time_rec != NULL)
+ gss_context_time(&tmpMinor, ctx, time_rec);
+ }
+
assert(ctx->state == EAP_STATE_ESTABLISHED || major == GSS_S_CONTINUE_NEEDED);
cleanup:
krb5_free_unparsed_name(krbContext, krbName);
- *output_name_type = GSS_EAP_NT_PRINCIPAL_NAME;
+ if (output_name_type != NULL)
+ *output_name_type = GSS_EAP_NT_PRINCIPAL_NAME;
return GSS_S_COMPLETE;
}
/* EAP includes */
#include <common.h>
#include <eap_peer/eap.h>
+#include <eap_peer/eap_i.h>
#include <eap_peer/eap_config.h>
#include <crypto/tls.h> /* XXX testing implementation only */
#include <wpabuf.h>
struct eap_gss_initiator_ctx {
unsigned int idleWhile;
struct eap_peer_config eapPeerConfig;
- struct eap_config eapConfig;
struct eap_sm *eap;
struct wpabuf reqData;
};
struct eap_eapol_interface *eapPolInterface;
void *tlsContext;
struct eap_sm *eap;
- struct eap_config eapConfig; /* XXX */
};
struct gss_ctx_id_struct {
}
return flag;
+
}
static struct eap_peer_config *
peerNotifyPending,
};
+extern int wpa_debug_level;
+
static OM_uint32
peerConfigInit(OM_uint32 *minor,
gss_cred_id_t cred,
GSSEAP_KRB_INIT(&krbContext);
if (loadConfig) {
+ eapPeerConfig->fragment_size = 1024;
+ wpa_debug_level = 0;
}
code = krb5_unparse_name(krbContext, cred->name->krbPrincipal, &identity);
}
static OM_uint32
-peerDeriveKey(OM_uint32 *minor,
- gss_ctx_id_t ctx)
+completeInit(OM_uint32 *minor,
+ gss_ctx_id_t ctx)
{
OM_uint32 major;
const unsigned char *key;
ctx->gssFlags &= ~(GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
}
+ sequenceInit(&ctx->seqState, ctx->recvSeq,
+ ((ctx->gssFlags & GSS_C_REPLAY_FLAG) != 0),
+ ((ctx->gssFlags & GSS_C_SEQUENCE_FLAG) != 0),
+ TRUE);
+
return GSS_S_COMPLETE;
}
gss_buffer_t inputToken,
gss_buffer_t outputToken)
{
- OM_uint32 major, tmpMinor;
+ OM_uint32 major;
+ OM_uint32 tmpMajor, tmpMinor;
time_t now;
int initialContextToken = 0, code;
+ struct wpabuf *resp = NULL;
initialContextToken = (inputToken == GSS_C_NO_BUFFER ||
inputToken->length == 0);
goto cleanup;
if (initialContextToken) {
+ struct eap_config eapConfig;
+
+ memset(&eapConfig, 0, sizeof(eapConfig));
ctx->flags |= CTX_FLAG_EAP_PORT_ENABLED;
ctx->initiatorCtx.eap = eap_peer_sm_init(ctx,
&gssEapPolicyCallbacks,
ctx,
- &ctx->initiatorCtx.eapConfig);
+ &eapConfig);
time(&now);
if (timeReq == 0 || timeReq == GSS_C_INDEFINITE)
}
if (GSS_ERROR(major))
goto cleanup;
+
+ resp = eap_sm_buildIdentity(ctx->initiatorCtx.eap, 0, 0);
+ major = GSS_S_CONTINUE_NEEDED;
+ goto cleanup;
+ } else {
+ ctx->flags |= CTX_FLAG_EAP_REQ; /* we have a Request from the acceptor */
}
wpabuf_set(&ctx->initiatorCtx.reqData,
inputToken->value, inputToken->length);
- code = eap_peer_sm_step(ctx->initiatorCtx.eap);
+ major = GSS_S_CONTINUE_NEEDED;
+ code = eap_peer_sm_step(ctx->initiatorCtx.eap);
if (ctx->flags & CTX_FLAG_EAP_RESP) {
- struct wpabuf *resp;
- gss_buffer_desc buf;
-
ctx->flags &= ~(CTX_FLAG_EAP_RESP);
resp = eap_get_eapRespData(ctx->initiatorCtx.eap);
-
- if (resp != NULL) {
- buf.length = wpabuf_len(resp);
- buf.value = (void *)wpabuf_head(resp);
-
- major = duplicateBuffer(minor, &buf, outputToken);
- if (GSS_ERROR(major))
- goto cleanup;
-
- major = GSS_S_CONTINUE_NEEDED;
- }
- }
-
- if (ctx->flags & CTX_FLAG_EAP_SUCCESS) {
- major = peerDeriveKey(minor, ctx);
- if (GSS_ERROR(major))
- goto cleanup;
-
+ } else if (ctx->flags & CTX_FLAG_EAP_SUCCESS) {
+ major = completeInit(minor, ctx);
ctx->flags &= ~(CTX_FLAG_EAP_SUCCESS);
ctx->state = EAP_STATE_ESTABLISHED;
- major = GSS_S_COMPLETE;
} else if ((ctx->flags & CTX_FLAG_EAP_FAIL) || code == 0) {
major = GSS_S_FAILURE;
}
cleanup:
+ if (resp != NULL) {
+ OM_uint32 tmpMajor;
+ gss_buffer_desc buf;
+
+ assert(major == GSS_S_CONTINUE_NEEDED);
+
+ buf.length = wpabuf_len(resp);
+ buf.value = (void *)wpabuf_head(resp);
+
+ tmpMajor = duplicateBuffer(&tmpMinor, &buf, outputToken);
+ if (GSS_ERROR(tmpMajor)) {
+ major = tmpMajor;
+ *minor = tmpMinor;
+ }
+ }
+
wpabuf_set(&ctx->initiatorCtx.reqData, NULL, 0);
peerConfigFree(&tmpMinor, ctx);
OM_uint32 *ret_flags,
OM_uint32 *time_rec)
{
- OM_uint32 major, tmpMinor;
+ OM_uint32 major;
+ OM_uint32 tmpMajor, tmpMinor;
gss_ctx_id_t ctx = *context_handle;
struct eap_gss_initiator_sm *sm = NULL;
gss_buffer_desc innerInputToken, innerOutputToken;
duplicateOid(&tmpMinor, ctx->mechanismUsed, actual_mech_type);
}
if (innerOutputToken.length != 0) {
- major = gssEapMakeToken(minor, ctx, &innerOutputToken,
- sm->outputTokenType, output_token);
- if (GSS_ERROR(major))
+ tmpMajor = gssEapMakeToken(&tmpMinor, ctx, &innerOutputToken,
+ sm->outputTokenType, output_token);
+ if (GSS_ERROR(tmpMajor)) {
+ major = tmpMajor;
+ *minor = tmpMinor;
goto cleanup;
+ }
}
if (ret_flags != NULL)
*ret_flags = ctx->gssFlags;
gss_delete_sec_context
gss_display_name
gss_display_name_ext
+gss_display_status
gss_duplicate_name
gss_export_name
+gss_export_name_composite
gss_export_sec_context
gss_get_mic
gss_get_name_attribute
gss_init_sec_context
gss_inquire_context
gss_inquire_cred
-gss_inquire_name
+gss_inquire_cred_by_oid
gss_inquire_mechs_for_name
+gss_inquire_name
gss_inquire_names_for_mech
+gss_inquire_sec_context_by_oid
gss_map_name_to_any
gss_process_context_token
gss_pseudo_random
gss_release_any_name_mapping
gss_release_cred
-gss_internal_release_oid
gss_release_name
+gss_internal_release_oid
gss_set_name_attribute
+gss_set_sec_context_option
gss_store_cred
gss_unwrap
gss_unwrap_iov
size_t dataLen, assocDataLen;
uint64_t seqnum;
int valid = 0;
- krb5_cksumtype cksumtype;
int conf_flag = 0;
krb5_context krbContext;
store_uint16_be(0, ptr + 4);
store_uint16_be(0, ptr + 6);
- code = gssEapVerify(krbContext, cksumtype, rrc,
+ code = gssEapVerify(krbContext, 0, rrc,
&ctx->rfc3961Key, keyUsage,
iov, iov_count, &valid);
if (code != 0 || valid == FALSE) {
goto defective;
seqnum = load_uint64_be(ptr + 8);
- code = gssEapVerify(krbContext, cksumtype, 0,
+ code = gssEapVerify(krbContext, 0, 0,
&ctx->rfc3961Key, keyUsage,
iov, iov_count, &valid);
if (code != 0 || valid == FALSE) {
gssEapReleaseName(&tmpMinor, &ctx->initiatorName);
gssEapReleaseName(&tmpMinor, &ctx->acceptorName);
gss_release_oid(&tmpMinor, &ctx->mechanismUsed);
- sequenceFree(ctx->seqState);
+ sequenceFree(&ctx->seqState);
GSSEAP_MUTEX_DESTROY(&ctx->mutex);
if (GSS_ERROR(major))
return major;
- if (ctx->mechanismUsed != GSS_C_NO_OID) {
+ if (ctx->mechanismUsed == GSS_C_NO_OID) {
if (!gssEapIsConcreteMechanismOid(oid))
return GSS_S_BAD_MECH;
if (code != 0)
goto cleanup;
- data.length = keyLength;
+ if (keyLength < keybytes) {
+ code = KRB5_BAD_MSIZE;
+ goto cleanup;
+ }
+
+ data.length = keybytes;
data.data = (char *)key;
kd.contents = GSSEAP_MALLOC(keylength);
if (code != 0)
goto cleanup;
- prf.length = prflength;
+ if (prflength < keybytes) {
+ code = KRB5_CRYPTO_INTERNAL;
+ goto cleanup;
+ }
+ prf.length = keybytes;
prf.data = GSSEAP_MALLOC(prflength);
if (data.data == NULL) {
code = ENOMEM;
gss_OID_desc toid;
ssize_t toksize = (ssize_t)toksize_in;
- if (toksize -= 1 < 0)
+ if ((toksize -= 1) < 0)
return ERANGE;
if (*buf++ != 0x60)
if (seqsize != toksize)
return ERANGE;
- if (toksize -= 1 < 0)
+ if ((toksize -= 1) < 0)
return ERANGE;
if (*buf++ != 0x06)
return EINVAL;
- if (toksize -= 1 < 0)
+ if ((toksize -= 1) < 0)
return ERANGE;
toid.length = *buf++;
- if (toksize -= toid.length < 0)
+ if ((toksize -= toid.length) < 0)
return ERANGE;
toid.elements = buf;
}
if (tok_type != TOK_TYPE_NONE) {
- if (toksize -= 2 < 0)
+ if ((toksize -= 2) < 0)
return EINVAL;
if ((*buf++ != ((tok_type >> 8) & 0xff)) ||
gss_buffer_t message_token,
gss_qop_t *qop_state)
{
- gss_iov_buffer_desc iov[2];
+ gss_iov_buffer_desc iov[3];
int conf_state;
+ if (message_token->length < 16) {
+ *minor = KRB5_BAD_MSIZE;
+ return GSS_S_BAD_SIG;
+ }
+
iov[0].type = GSS_IOV_BUFFER_TYPE_DATA;
iov[0].buffer = *message_buffer;
iov[1].type = GSS_IOV_BUFFER_TYPE_HEADER;
- iov[1].buffer = *message_token;
+ iov[1].buffer.length = 16;
+ iov[1].buffer.value = message_token->value;
+
+ iov[2].type = GSS_IOV_BUFFER_TYPE_TRAILER;
+ iov[2].buffer.length = message_token->length - 16;
+ iov[2].buffer.value = (unsigned char *)message_token->value + 16;
return gssEapUnwrapOrVerifyMIC(minor, ctx, &conf_state, qop_state,
- iov, 2, TOK_TYPE_MIC);
+ iov, 3, TOK_TYPE_MIC);
}
*minor = code;
- if (code == 0)
- return GSS_S_FAILURE;
- else
- return GSS_S_COMPLETE;
+ return (code == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE;
}
OM_uint32