svn rev #25627: branches/krb5-1-10/src/lib/gssapi/spnego/

tlyu@MIT.EDU tlyu at MIT.EDU
Mon Jan 9 16:23:40 EST 2012


http://src.mit.edu/fisheye/changelog/krb5/?cs=25627
Commit By: tlyu
Log Message:
ticket: 7053
version_fixed: 1.10
status: resolved

Pull up r25590 from trunk

 ------------------------------------------------------------------------
 r25590 | ghudson | 2011-12-16 18:18:54 -0500 (Fri, 16 Dec 2011) | 11 lines

 ticket: 7053
 subject: Verify acceptor's mech in SPNEGO initiator
 target_version: 1.10
 tags: pullup

 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.


Changed Files:
U   branches/krb5-1-10/src/lib/gssapi/spnego/gssapiP_spnego.h
U   branches/krb5-1-10/src/lib/gssapi/spnego/spnego_mech.c
Modified: branches/krb5-1-10/src/lib/gssapi/spnego/gssapiP_spnego.h
===================================================================
--- branches/krb5-1-10/src/lib/gssapi/spnego/gssapiP_spnego.h	2012-01-09 21:03:58 UTC (rev 25626)
+++ branches/krb5-1-10/src/lib/gssapi/spnego/gssapiP_spnego.h	2012-01-09 21:23:40 UTC (rev 25627)
@@ -91,7 +91,8 @@
 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;

Modified: branches/krb5-1-10/src/lib/gssapi/spnego/spnego_mech.c
===================================================================
--- branches/krb5-1-10/src/lib/gssapi/spnego/spnego_mech.c	2012-01-09 21:03:58 UTC (rev 25626)
+++ branches/krb5-1-10/src/lib/gssapi/spnego/spnego_mech.c	2012-01-09 21:23:40 UTC (rev 25627)
@@ -118,7 +118,7 @@
 
 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 @@
 		 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 @@
 
 	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 @@
 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 @@
 
 cleanup:
 	release_spnego_ctx(&sc);
-	gss_release_oid_set(&tmpmin, mechSet);
 	return ret;
 }
 
@@ -780,24 +770,22 @@
 		  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 @@
 	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 @@
 	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 @@
 		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 @@
 	 * 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 @@
 	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 @@
 		(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 @@
  * 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;;
+		if (g_OID_equal(mech_oid, &gss_mech_krb5_wrong_oid))
+			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);
+		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);



More information about the cvs-krb5 mailing list