summaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2011-12-16 23:18:54 +0000
committerGreg Hudson <ghudson@mit.edu>2011-12-16 23:18:54 +0000
commitcd7d6b08aebaee50a25a8eb519588abbca633d72 (patch)
treed16f7949bd87bdc7083958547e6c2d7b091238bb /src/lib
parent2177db67e3943ac8a6076642ffc81a7d90803890 (diff)
downloadkrb5-cd7d6b08aebaee50a25a8eb519588abbca633d72.tar.gz
krb5-cd7d6b08aebaee50a25a8eb519588abbca633d72.tar.xz
krb5-cd7d6b08aebaee50a25a8eb519588abbca633d72.zip
Verify acceptor's mech in SPNEGO initiator
In spnego_gss_ctx_id_rec, store the set of negotiable mechanisms as well as the currently selected internal_mech, which becomes an alias into mech_set. In init_ctx_reselect, locate the acceptor's counter- proposal in sc->mech_set and consider the token defective if it is not found. ticket: 7053 target_version: 1.10 tags: pullup git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25590 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/gssapi/spnego/gssapiP_spnego.h3
-rw-r--r--src/lib/gssapi/spnego/spnego_mech.c119
2 files changed, 44 insertions, 78 deletions
diff --git a/src/lib/gssapi/spnego/gssapiP_spnego.h b/src/lib/gssapi/spnego/gssapiP_spnego.h
index 4c1b4beab..3fe9fca74 100644
--- a/src/lib/gssapi/spnego/gssapiP_spnego.h
+++ b/src/lib/gssapi/spnego/gssapiP_spnego.h
@@ -91,7 +91,8 @@ typedef struct {
typedef struct {
OM_uint32 magic_num;
gss_buffer_desc DER_mechTypes;
- gss_OID internal_mech;
+ gss_OID_set mech_set;
+ gss_OID internal_mech; /* alias into mech_set->elements */
gss_ctx_id_t ctx_handle;
char *optionStr;
gss_cred_id_t default_cred;
diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c
index 657a2f8ca..ca23b2248 100644
--- a/src/lib/gssapi/spnego/spnego_mech.c
+++ b/src/lib/gssapi/spnego/spnego_mech.c
@@ -118,7 +118,7 @@ handle_mic(OM_uint32 *, gss_buffer_t, int, spnego_gss_ctx_id_t,
static OM_uint32
init_ctx_new(OM_uint32 *, spnego_gss_cred_id_t, gss_ctx_id_t *,
- gss_OID_set *, send_token_flag *);
+ send_token_flag *);
static OM_uint32
init_ctx_nego(OM_uint32 *, spnego_gss_ctx_id_t, OM_uint32, gss_OID,
gss_buffer_t *, gss_buffer_t *,
@@ -155,8 +155,7 @@ acc_ctx_call_acc(OM_uint32 *, spnego_gss_ctx_id_t, spnego_gss_cred_id_t,
OM_uint32 *, send_token_flag *);
static gss_OID
-negotiate_mech_type(OM_uint32 *, gss_OID_set, gss_OID_set,
- OM_uint32 *);
+negotiate_mech(gss_OID_set, gss_OID_set, OM_uint32 *);
static int
g_get_tag_and_length(unsigned char **, int, unsigned int, unsigned int *);
@@ -439,6 +438,7 @@ create_spnego_ctx(void)
spnego_ctx->magic_num = SPNEGO_MAGIC_ID;
spnego_ctx->ctx_handle = GSS_C_NO_CONTEXT;
+ spnego_ctx->mech_set = NULL;
spnego_ctx->internal_mech = NULL;
spnego_ctx->optionStr = NULL;
spnego_ctx->DER_mechTypes.length = 0;
@@ -576,34 +576,25 @@ static OM_uint32
init_ctx_new(OM_uint32 *minor_status,
spnego_gss_cred_id_t spcred,
gss_ctx_id_t *ctx,
- gss_OID_set *mechSet,
send_token_flag *tokflag)
{
- OM_uint32 ret, tmpmin;
+ OM_uint32 ret;
spnego_gss_ctx_id_t sc = NULL;
+ sc = create_spnego_ctx();
+ if (sc == NULL)
+ return GSS_S_FAILURE;
+
/* determine negotiation mech set */
ret = get_negotiable_mechs(minor_status, spcred, GSS_C_INITIATE,
- mechSet);
+ &sc->mech_set);
if (ret != GSS_S_COMPLETE)
return ret;
- sc = create_spnego_ctx();
- if (sc == NULL)
- return GSS_S_FAILURE;
+ /* Set an initial internal mech to make the first context token. */
+ sc->internal_mech = &sc->mech_set->elements[0];
- /*
- * need to pull the first mech from mechSet to do first
- * gss_init_sec_context()
- */
- ret = generic_gss_copy_oid(minor_status, (*mechSet)->elements,
- &sc->internal_mech);
- if (ret != GSS_S_COMPLETE) {
- map_errcode(minor_status);
- goto cleanup;
- }
-
- if (put_mech_set(*mechSet, &sc->DER_mechTypes) < 0) {
+ if (put_mech_set(sc->mech_set, &sc->DER_mechTypes) < 0) {
ret = GSS_S_FAILURE;
goto cleanup;
}
@@ -619,7 +610,6 @@ init_ctx_new(OM_uint32 *minor_status,
cleanup:
release_spnego_ctx(&sc);
- gss_release_oid_set(&tmpmin, mechSet);
return ret;
}
@@ -780,24 +770,22 @@ init_ctx_reselect(OM_uint32 *minor_status, spnego_gss_ctx_id_t sc,
gss_buffer_t *responseToken, gss_buffer_t *mechListMIC,
OM_uint32 *negState, send_token_flag *tokflag)
{
- OM_uint32 ret, tmpmin;
+ OM_uint32 tmpmin;
+ size_t i;
generic_gss_release_oid(&tmpmin, &sc->internal_mech);
gss_delete_sec_context(&tmpmin, &sc->ctx_handle,
GSS_C_NO_BUFFER);
- ret = generic_gss_copy_oid(minor_status, supportedMech,
- &sc->internal_mech);
- if (ret != GSS_S_COMPLETE) {
- map_errcode(minor_status);
- sc->internal_mech = GSS_C_NO_OID;
- *tokflag = NO_TOKEN_SEND;
- return ret;
+ /* Find supportedMech in sc->mech_set. */
+ for (i = 0; i < sc->mech_set->count; i++) {
+ if (g_OID_equal(supportedMech, &sc->mech_set->elements[i]))
+ break;
}
- if (*responseToken != GSS_C_NO_BUFFER) {
- /* Reject spurious mech token. */
+ if (i == sc->mech_set->count)
return GSS_S_DEFECTIVE_TOKEN;
- }
+ sc->internal_mech = &sc->mech_set->elements[i];
+
/*
* Windows 2003 and earlier don't correctly send a
* negState of request-mic when counter-proposing a
@@ -907,7 +895,6 @@ spnego_gss_init_sec_context(
OM_uint32 tmpmin, ret, negState;
gss_buffer_t mechtok_in, mechListMIC_in, mechListMIC_out;
gss_buffer_desc mechtok_out = GSS_C_EMPTY_BUFFER;
- gss_OID_set mechSet = GSS_C_NO_OID_SET;
spnego_gss_cred_id_t spcred = NULL;
spnego_gss_ctx_id_t spnego_ctx = NULL;
@@ -957,7 +944,7 @@ spnego_gss_init_sec_context(
spcred = (spnego_gss_cred_id_t)claimant_cred_handle;
if (*context_handle == GSS_C_NO_CONTEXT) {
ret = init_ctx_new(minor_status, spcred,
- context_handle, &mechSet, &send_token);
+ context_handle, &send_token);
if (ret != GSS_S_CONTINUE_NEEDED) {
goto cleanup;
}
@@ -1045,9 +1032,6 @@ cleanup:
gss_release_buffer(&tmpmin, mechListMIC_out);
free(mechListMIC_out);
}
- if (mechSet != GSS_C_NO_OID_SET) {
- gss_release_oid_set(&tmpmin, &mechSet);
- }
return ret;
} /* init_sec_context */
@@ -1344,10 +1328,7 @@ acc_ctx_new(OM_uint32 *minor_status,
* that the initiator requested and the list that
* the acceptor will support.
*/
- mech_wanted = negotiate_mech_type(minor_status,
- supported_mechSet,
- mechTypes,
- negState);
+ mech_wanted = negotiate_mech(supported_mechSet, mechTypes, negState);
if (*negState == REJECT) {
ret = GSS_S_BAD_MECH;
goto cleanup;
@@ -1361,9 +1342,10 @@ acc_ctx_new(OM_uint32 *minor_status,
if (sc == NULL) {
ret = GSS_S_FAILURE;
*return_token = NO_TOKEN_SEND;
- generic_gss_release_oid(&tmpmin, &mech_wanted);
goto cleanup;
}
+ sc->mech_set = supported_mechSet;
+ supported_mechSet = GSS_C_NO_OID_SET;
sc->internal_mech = mech_wanted;
sc->DER_mechTypes = der_mechTypes;
der_mechTypes.length = 0;
@@ -2810,8 +2792,7 @@ release_spnego_ctx(spnego_gss_ctx_id_t *ctx)
(void) gss_release_buffer(&minor_stat,
&context->DER_mechTypes);
- (void) generic_gss_release_oid(&minor_stat,
- &context->internal_mech);
+ (void) gss_release_oid_set(&minor_stat, &context->mech_set);
(void) gss_release_name(&minor_stat, &context->internal_name);
@@ -3429,48 +3410,32 @@ put_negResult(unsigned char **buf_out, OM_uint32 negResult,
* chosen as the negotiated mechanism. If one is found, negResult
* is set to ACCEPT_INCOMPLETE if it's the first mech, REQUEST_MIC if
* it's not the first mech, otherwise we return NULL and negResult
- * is set to REJECT.
+ * is set to REJECT. The returned pointer is an alias into
+ * supported->elements and should not be freed.
*
* NOTE: There is currently no way to specify a preference order of
* mechanisms supported by the acceptor.
*/
static gss_OID
-negotiate_mech_type(OM_uint32 *minor_status,
- gss_OID_set supported_mechSet,
- gss_OID_set mechset,
- OM_uint32 *negResult)
+negotiate_mech(gss_OID_set supported, gss_OID_set received,
+ OM_uint32 *negResult)
{
- gss_OID returned_mech;
- OM_uint32 status;
- int present;
- unsigned int i;
+ size_t i, j;
- for (i = 0; i < mechset->count; i++) {
- gss_OID mech_oid = &mechset->elements[i];
+ for (i = 0; i < received->count; i++) {
+ gss_OID mech_oid = &received->elements[i];
/* Accept wrong mechanism OID from MS clients */
- if (mech_oid->length == gss_mech_krb5_wrong_oid.length &&
- memcmp(mech_oid->elements, gss_mech_krb5_wrong_oid.elements, mech_oid->length) == 0)
- mech_oid = (gss_OID)&gss_mech_krb5_oid;;
-
- gss_test_oid_set_member(minor_status, mech_oid, supported_mechSet, &present);
- if (!present)
- continue;
-
- if (i == 0)
- *negResult = ACCEPT_INCOMPLETE;
- else
- *negResult = REQUEST_MIC;
-
- status = generic_gss_copy_oid(minor_status,
- &mechset->elements[i],
- &returned_mech);
- if (status != GSS_S_COMPLETE) {
- *negResult = REJECT;
- map_errcode(minor_status);
- return (NULL);
+ if (g_OID_equal(mech_oid, &gss_mech_krb5_wrong_oid))
+ mech_oid = (gss_OID)&gss_mech_krb5_oid;
+
+ for (j = 0; j < supported->count; j++) {
+ if (g_OID_equal(mech_oid, &supported->elements[j])) {
+ *negResult = (i == 0) ? ACCEPT_INCOMPLETE :
+ REQUEST_MIC;
+ return &supported->elements[j];
+ }
}
- return (returned_mech);
}
*negResult = REJECT;
return (NULL);