From: Luke Howard Date: Thu, 9 Sep 2010 10:59:06 +0000 (+0200) Subject: Refactor X-Git-Tag: vm/20110310~358 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mech_eap.orig;a=commitdiff_plain;h=c782e76527626566bb4d6fddf38f83beea0aa72a Refactor --- diff --git a/Makefile.am b/Makefile.am index 4637ad6..7cbe203 100644 --- a/Makefile.am +++ b/Makefile.am @@ -54,6 +54,7 @@ libmech_eap_la_SOURCES = \ store_cred.c \ unwrap.c \ unwrap_iov.c \ + util_buffer.c \ util_context.c \ util_cksum.c \ util_cred.c \ diff --git a/accept_sec_context.c b/accept_sec_context.c index fe2c8dd..25f35ce 100644 --- a/accept_sec_context.c +++ b/accept_sec_context.c @@ -32,11 +32,39 @@ #include "gssapiP_eap.h" +static OM_uint32 +eapGssSmAcceptAuthenticate(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; + +cleanup: + return major; +} + + +static struct eap_gss_acceptor_sm { + enum gss_eap_token_type inputTokenType; + enum gss_eap_token_type outputTokenType; + OM_uint32 (*processToken)(OM_uint32 *, + gss_ctx_id_t, + gss_cred_id_t, + gss_buffer_t, + gss_channel_bindings_t, + gss_buffer_t); +} eapGssAcceptorSm[] = { + { TOK_TYPE_EAP_RESP, TOK_TYPE_EAP_REQ, NULL }, +}; + OM_uint32 gss_accept_sec_context(OM_uint32 *minor, gss_ctx_id_t *context_handle, - gss_cred_id_t acceptor_cred_handle, - gss_buffer_t input_token_buffer, + 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, @@ -45,5 +73,84 @@ gss_accept_sec_context(OM_uint32 *minor, OM_uint32 *time_rec, gss_cred_id_t *delegated_cred_handle) { - GSSEAP_NOT_IMPLEMENTED; + OM_uint32 major, tmpMinor; + gss_ctx_id_t ctx = *context_handle; + struct eap_gss_acceptor_sm *sm = NULL; + gss_buffer_desc innerInputToken, innerOutputToken; + + *minor = 0; + + innerOutputToken.length = 0; + innerOutputToken.value = NULL; + + output_token->length = 0; + output_token->value = NULL; + + if (cred != GSS_C_NO_CREDENTIAL && !(cred->flags & CRED_FLAG_ACCEPT)) { + return GSS_S_NO_CRED; + } + + if (input_token == GSS_C_NO_BUFFER || input_token->length == 0) { + return GSS_S_DEFECTIVE_TOKEN; + } + + if (ctx == GSS_C_NO_CONTEXT) { + major = gssEapAllocContext(minor, &ctx); + if (GSS_ERROR(major)) + return major; + + *context_handle = ctx; + } + + GSSEAP_MUTEX_LOCK(&ctx->mutex); + + sm = &eapGssAcceptorSm[ctx->state]; + + major = gssEapVerifyToken(minor, ctx, input_token, + sm->inputTokenType, &innerInputToken); + if (GSS_ERROR(major)) + goto cleanup; + + major = (sm->processToken)(minor, + ctx, + cred, + &innerInputToken, + input_chan_bindings, + &innerOutputToken); + if (GSS_ERROR(major)) + goto cleanup; + + 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)) + 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; + + assert(ctx->state == EAP_STATE_ESTABLISHED || major == GSS_S_CONTINUE_NEEDED); + +cleanup: + GSSEAP_MUTEX_UNLOCK(&ctx->mutex); + + if (GSS_ERROR(major)) + gssEapReleaseContext(&tmpMinor, context_handle); + + gss_release_buffer(&tmpMinor, &innerOutputToken); + + return major; } diff --git a/gssapiP_eap.h b/gssapiP_eap.h index 1427272..2483924 100644 --- a/gssapiP_eap.h +++ b/gssapiP_eap.h @@ -124,13 +124,6 @@ struct eap_gss_initiator_ctx { struct eap_gss_acceptor_ctx { }; -typedef OM_uint32 (*eap_gss_acceptor_sm)(OM_uint32 *, - gss_ctx_id_t, - gss_cred_id_t, - gss_buffer_t, - gss_channel_bindings_t, - gss_buffer_t); - struct gss_ctx_id_struct { GSSEAP_MUTEX mutex; enum eap_gss_state state; diff --git a/init_sec_context.c b/init_sec_context.c index 5075ed8..b9ff0be 100644 --- a/init_sec_context.c +++ b/init_sec_context.c @@ -140,46 +140,45 @@ peerSetInt(void *data, enum eapol_int_var variable, } static OM_uint32 -eapGssSmAuthenticate(OM_uint32 *minor, - gss_cred_id_t cred, - gss_ctx_id_t ctx, - 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_buffer_t output_token) +eapGssSmInitAuthenticate(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) { OM_uint32 major, tmpMinor; time_t now; - if (input_token == GSS_C_NO_BUFFER || input_token->length == 0) { + if (inputToken == GSS_C_NO_BUFFER || inputToken->length == 0) { /* first time */ - req_flags &= GSS_C_TRANS_FLAG | GSS_C_REPLAY_FLAG | GSS_C_DCE_STYLE; - ctx->gssFlags |= req_flags; + reqFlags &= GSS_C_TRANS_FLAG | GSS_C_REPLAY_FLAG | GSS_C_DCE_STYLE; + ctx->gssFlags |= reqFlags; time(&now); - if (time_req == 0 || time_req == GSS_C_INDEFINITE) + if (timeReq == 0 || timeReq == GSS_C_INDEFINITE) ctx->expiryTime = 0; else - ctx->expiryTime = now + time_req; + ctx->expiryTime = now + timeReq; major = gss_duplicate_name(minor, cred->name, &ctx->initiatorName); if (GSS_ERROR(major)) goto cleanup; - major = gss_duplicate_name(minor, target_name, &ctx->acceptorName); + major = gss_duplicate_name(minor, target, &ctx->acceptorName); if (GSS_ERROR(major)) goto cleanup; - if (mech_type == GSS_C_NULL_OID || - oidEqual(mech_type, GSS_EAP_MECHANISM)) { + if (mech == GSS_C_NULL_OID || oidEqual(mech, GSS_EAP_MECHANISM)) { major = gssEapDefaultMech(minor, &ctx->mechanismUsed); - } else if (gssEapIsMechanismOid(mech_type)) { - if (!gssEapInternalizeOid(mech_type, &ctx->mechanismUsed)) - major = duplicateOid(minor, mech_type, &ctx->mechanismUsed); + } else if (gssEapIsConcreteMechanismOid(mech)) { + if (!gssEapInternalizeOid(mech, &ctx->mechanismUsed)) + major = duplicateOid(minor, mech, &ctx->mechanismUsed); } else { major = GSS_S_BAD_MECH; } @@ -205,13 +204,13 @@ static struct eap_gss_initiator_sm { gss_buffer_t, gss_buffer_t); } eapGssInitiatorSm[] = { - { TOK_TYPE_EAP_REQ, TOK_TYPE_EAP_RESP, eapGssSmAuthenticate }, + { TOK_TYPE_EAP_REQ, TOK_TYPE_EAP_RESP, eapGssSmInitAuthenticate }, }; OM_uint32 gss_init_sec_context(OM_uint32 *minor, gss_cred_id_t cred, - gss_ctx_id_t *pCtx, + gss_ctx_id_t *context_handle, gss_name_t target_name, gss_OID mech_type, OM_uint32 req_flags, @@ -224,7 +223,7 @@ gss_init_sec_context(OM_uint32 *minor, OM_uint32 *time_rec) { OM_uint32 major, tmpMinor; - gss_ctx_id_t ctx = *pCtx; + gss_ctx_id_t ctx = *context_handle; struct eap_gss_initiator_sm *sm = NULL; gss_buffer_desc innerInputToken, innerOutputToken; @@ -237,23 +236,25 @@ gss_init_sec_context(OM_uint32 *minor, output_token->value = NULL; if (cred != GSS_C_NO_CREDENTIAL && !(cred->flags & CRED_FLAG_INITIATE)) { - major = GSS_S_NO_CRED; - goto cleanup; + return GSS_S_NO_CRED; } if (ctx == GSS_C_NO_CONTEXT) { if (input_token != GSS_C_NO_BUFFER && input_token->length != 0) { - major = GSS_S_DEFECTIVE_TOKEN; - goto cleanup; + return GSS_S_DEFECTIVE_TOKEN; } major = gssEapAllocContext(minor, &ctx); if (GSS_ERROR(major)) - goto cleanup; + return major; + + ctx->flags |= CTX_FLAG_INITIATOR; - *pCtx = ctx; + *context_handle = ctx; } + GSSEAP_MUTEX_LOCK(&ctx->mutex); + sm = &eapGssInitiatorSm[ctx->state]; if (input_token != GSS_C_NO_BUFFER) { @@ -274,32 +275,33 @@ gss_init_sec_context(OM_uint32 *minor, req_flags, time_req, input_chan_bindings, - input_token, - output_token); + &innerInputToken, + &innerOutputToken); if (GSS_ERROR(major)) goto cleanup; - if (output_token->length != 0) { + if (actual_mech_type != NULL) { + if (!gssEapInternalizeOid(ctx->mechanismUsed, actual_mech_type)) + duplicateOid(&tmpMinor, ctx->mechanismUsed, actual_mech_type); + } + if (innerOutputToken.length != 0) { major = gssEapMakeToken(minor, ctx, &innerOutputToken, sm->outputTokenType, output_token); if (GSS_ERROR(major)) goto cleanup; } - - if (actual_mech_type != NULL) { - if (!gssEapInternalizeOid(ctx->mechanismUsed, actual_mech_type)) - duplicateOid(&tmpMinor, ctx->mechanismUsed, actual_mech_type); - } if (ret_flags != NULL) *ret_flags = ctx->gssFlags; if (time_rec != NULL) gss_context_time(&tmpMinor, ctx, time_rec); - assert(ctx->state == EAP_STATE_ESTABLISHED || output_token->length != 0); + assert(ctx->state == EAP_STATE_ESTABLISHED || major == GSS_S_CONTINUE_NEEDED); cleanup: + GSSEAP_MUTEX_UNLOCK(&ctx->mutex); + if (GSS_ERROR(major)) - gssEapReleaseContext(&tmpMinor, pCtx); + gssEapReleaseContext(&tmpMinor, context_handle); gss_release_buffer(&tmpMinor, &innerOutputToken); diff --git a/util.h b/util.h index 5be9538..0fceafe 100644 --- a/util.h +++ b/util.h @@ -76,6 +76,23 @@ enum gss_eap_token_type { TOK_TYPE_GSS_CHANNEL_BINDINGS = 0x0603, /* draft-howlett-eap-gss */ }; +/* util_buffer.c */ +OM_uint32 +makeStringBuffer(OM_uint32 *minor, + const char *string, + gss_buffer_t buffer); + +OM_uint32 +bufferToString(OM_uint32 *minor, + const gss_buffer_t buffer, + char **pString); + +OM_uint32 +duplicateBuffer(OM_uint32 *minor, + const gss_buffer_t src, + gss_buffer_t dst); + +/* util_cksum.c */ int gssEapSign(krb5_context context, krb5_cksumtype type, @@ -206,6 +223,9 @@ gssEapOidToEnctype(OM_uint32 *minor, int gssEapIsMechanismOid(const gss_OID oid); +int +gssEapIsConcreteMechanismOid(const gss_OID oid); + OM_uint32 gssEapValidateMechs(OM_uint32 *minor, const gss_OID_set mechs); @@ -312,7 +332,7 @@ makeTokenHeader(const gss_OID_desc *mech, enum gss_eap_token_type tok_type); int -verifyTokenHeader(const gss_OID_desc * mech, +verifyTokenHeader(gss_OID mech, size_t *body_size, unsigned char **buf_in, size_t toksize_in, @@ -411,70 +431,4 @@ load_uint64_be(const void *cvp) return ((uint64_t)load_uint32_be(p) << 32) | load_uint32_be(p + 4); } -static OM_uint32 -makeStringBuffer(OM_uint32 *minor, - const char *string, - gss_buffer_t buffer) -{ - size_t len = strlen(string); - - buffer->value = GSSEAP_MALLOC(len + 1); - if (buffer->value == NULL) { - *minor = ENOMEM; - return GSS_S_FAILURE; - } - memcpy(buffer->value, string, len + 1); - buffer->length = len; - - *minor = 0; - return GSS_S_COMPLETE; -} - -static OM_uint32 -bufferToString(OM_uint32 *minor, - const gss_buffer_t buffer, - char **pString) -{ - char *s; - - s = GSSEAP_MALLOC(buffer->length + 1); - if (s == NULL) { - *minor = ENOMEM; - return GSS_S_FAILURE; - } - memcpy(s, buffer->value, buffer->length); - s[buffer->length] = '\0'; - - *pString = s; - - *minor = 0; - return GSS_S_COMPLETE; -} - -static OM_uint32 -duplicateBuffer(OM_uint32 *minor, - const gss_buffer_t src, - gss_buffer_t dst) -{ - dst->length = 0; - dst->value = NULL; - - if (src == GSS_C_NO_BUFFER) - return GSS_S_COMPLETE; - - dst->value = GSSEAP_MALLOC(src->length + 1); - if (dst->value == NULL) { - *minor = ENOMEM; - return GSS_S_FAILURE; - } - - dst->length = src->length; - memcpy(dst->value, src->value, dst->length); - - ((unsigned char *)dst->value)[dst->length] = '\0'; - - *minor = 0; - return GSS_S_COMPLETE; -} - #endif /* _UTIL_H_ */ diff --git a/util_buffer.c b/util_buffer.c new file mode 100644 index 0000000..df1c0ac --- /dev/null +++ b/util_buffer.c @@ -0,0 +1,99 @@ +/* + * 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" + +OM_uint32 +makeStringBuffer(OM_uint32 *minor, + const char *string, + gss_buffer_t buffer) +{ + size_t len = strlen(string); + + buffer->value = GSSEAP_MALLOC(len + 1); + if (buffer->value == NULL) { + *minor = ENOMEM; + return GSS_S_FAILURE; + } + memcpy(buffer->value, string, len + 1); + buffer->length = len; + + *minor = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 +bufferToString(OM_uint32 *minor, + const gss_buffer_t buffer, + char **pString) +{ + char *s; + + s = GSSEAP_MALLOC(buffer->length + 1); + if (s == NULL) { + *minor = ENOMEM; + return GSS_S_FAILURE; + } + memcpy(s, buffer->value, buffer->length); + s[buffer->length] = '\0'; + + *pString = s; + + *minor = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 +duplicateBuffer(OM_uint32 *minor, + const gss_buffer_t src, + gss_buffer_t dst) +{ + dst->length = 0; + dst->value = NULL; + + if (src == GSS_C_NO_BUFFER) + return GSS_S_COMPLETE; + + dst->value = GSSEAP_MALLOC(src->length + 1); + if (dst->value == NULL) { + *minor = ENOMEM; + return GSS_S_FAILURE; + } + + dst->length = src->length; + memcpy(dst->value, src->value, dst->length); + + ((unsigned char *)dst->value)[dst->length] = '\0'; + + *minor = 0; + return GSS_S_COMPLETE; +} diff --git a/util_context.c b/util_context.c index d777b17..6e2715a 100644 --- a/util_context.c +++ b/util_context.c @@ -88,7 +88,7 @@ OM_uint32 gssEapReleaseContext(OM_uint32 *minor, gss_ctx_id_t *pCtx) { - OM_uint32 major, tmpMinor; + OM_uint32 tmpMinor; gss_ctx_id_t ctx = *pCtx; krb5_context krbContext = NULL; @@ -127,7 +127,6 @@ gssEapMakeToken(OM_uint32 *minor, enum gss_eap_token_type tokenType, gss_buffer_t outputToken) { - OM_uint32 major; unsigned char *p; outputToken->length = tokenSize(ctx->mechanismUsed, innerToken->length); @@ -155,12 +154,32 @@ gssEapVerifyToken(OM_uint32 *minor, OM_uint32 major; size_t bodySize; unsigned char *p = (unsigned char *)inputToken->value; + gss_OID_desc oidBuf; + gss_OID oid; + + if (ctx->mechanismUsed != GSS_C_NO_OID) { + oid = ctx->mechanismUsed; + } else { + oidBuf.elements = NULL; + oidBuf.length = 0; + oid = &oidBuf; + } - major = verifyTokenHeader(ctx->mechanismUsed, &bodySize, &p, - inputToken->length, tokenType); + major = verifyTokenHeader(oid, &bodySize, &p, inputToken->length, tokenType); if (GSS_ERROR(major)) return major; + if (ctx->mechanismUsed != GSS_C_NO_OID) { + if (!gssEapIsConcreteMechanismOid(oid)) + return GSS_S_BAD_MECH; + + if (!gssEapInternalizeOid(oid, &ctx->mechanismUsed)) { + major = duplicateOid(minor, oid, &ctx->mechanismUsed); + if (GSS_ERROR(major)) + return major; + } + } + innerInputToken->length = bodySize; innerInputToken->value = p; diff --git a/util_mech.c b/util_mech.c index 4aece80..2919b34 100644 --- a/util_mech.c +++ b/util_mech.c @@ -66,19 +66,19 @@ gss_OID GSS_EAP_AES128_CTS_HMAC_SHA1_96_MECHANISM = &gssEapConcreteMechs[1]; gss_OID GSS_EAP_AES256_CTS_HMAC_SHA1_96_MECHANISM = &gssEapConcreteMechs[2]; int -gssEapIsMechanismOid(const gss_OID oid) +gssEapIsConcreteMechanismOid(const gss_OID oid) { - if (oid == GSS_C_NO_OID) { - return TRUE; - } else if (oidEqual(oid, GSS_EAP_MECHANISM)) { - return TRUE; - } else if (oid->length > gssEapMechPrefix.length && - memcmp(oid->elements, gssEapMechPrefix.elements, - gssEapMechPrefix.length) == 0) { - return TRUE; - } + return oid->length > gssEapMechPrefix.length && + memcmp(oid->elements, gssEapMechPrefix.elements, + gssEapMechPrefix.length) == 0; +} - return FALSE; +int +gssEapIsMechanismOid(const gss_OID oid) +{ + return oid == GSS_C_NO_OID || + oidEqual(oid, GSS_EAP_MECHANISM) || + gssEapIsConcreteMechanismOid(oid); } OM_uint32 diff --git a/util_token.c b/util_token.c index bb7ef7a..e089690 100644 --- a/util_token.c +++ b/util_token.c @@ -197,12 +197,11 @@ makeTokenHeader( */ int -verifyTokenHeader( - const gss_OID_desc * mech, - size_t *body_size, - unsigned char **buf_in, - size_t toksize_in, - enum gss_eap_token_type tok_type) +verifyTokenHeader(gss_OID mech, + size_t *body_size, + unsigned char **buf_in, + size_t toksize_in, + enum gss_eap_token_type tok_type) { unsigned char *buf = *buf_in; ssize_t seqsize; @@ -239,8 +238,13 @@ verifyTokenHeader( toid.elements = buf; buf += toid.length; - if (!oidEqual(&toid, mech)) + if (mech->elements == NULL) { + *mech = toid; + if (toid.length == 0) + return EINVAL; + } else if (!oidEqual(&toid, mech)) { return EINVAL; + } if (tok_type != TOK_TYPE_NONE) { if (toksize -= 2 < 0)