ea319dd
From 748617c1b8d1550284157a79bc7aeb6295a27bf4 Mon Sep 17 00:00:00 2001
1560d2b
From: Simo Sorce <simo@redhat.com>
1560d2b
Date: Fri, 13 Nov 2015 14:54:11 -0500
b8e88a1
Subject: [PATCH] Fix impersonate_name to work with interposers
1560d2b
1560d2b
This follows the same modifications applied to
1560d2b
gss_acquire_cred_with_password() when interposer plugins were
1560d2b
introduced.
1560d2b
1560d2b
[ghudson@mit.edu: minor whitespace changes; initialize out_mcred in
1560d2b
spnego_gss_acquire_cred_impersonate_name() since it is released in the
1560d2b
cleanup handler]
1560d2b
1560d2b
ticket: 8280 (new)
1560d2b
---
1560d2b
 src/lib/gssapi/mechglue/g_acquire_cred_imp_name.c | 58 +++++++++++++++--------
1560d2b
 src/lib/gssapi/spnego/spnego_mech.c               | 35 +++++++-------
1560d2b
 2 files changed, 54 insertions(+), 39 deletions(-)
1560d2b
1560d2b
diff --git a/src/lib/gssapi/mechglue/g_acquire_cred_imp_name.c b/src/lib/gssapi/mechglue/g_acquire_cred_imp_name.c
1560d2b
index 0dd4f87..9eab25e 100644
1560d2b
--- a/src/lib/gssapi/mechglue/g_acquire_cred_imp_name.c
1560d2b
+++ b/src/lib/gssapi/mechglue/g_acquire_cred_imp_name.c
1560d2b
@@ -334,6 +334,8 @@ gss_add_cred_impersonate_name(OM_uint32 *minor_status,
1560d2b
     gss_cred_id_t	cred = NULL;
1560d2b
     gss_OID		new_mechs_array = NULL;
1560d2b
     gss_cred_id_t *	new_cred_array = NULL;
1560d2b
+    gss_OID_set		target_mechs = GSS_C_NO_OID_SET;
1560d2b
+    gss_OID		selected_mech = GSS_C_NO_OID;
1560d2b
 
1560d2b
     status = val_add_cred_impersonate_name_args(minor_status,
1560d2b
 						input_cred_handle,
1560d2b
@@ -350,7 +352,12 @@ gss_add_cred_impersonate_name(OM_uint32 *minor_status,
1560d2b
     if (status != GSS_S_COMPLETE)
1560d2b
 	return (status);
1560d2b
 
1560d2b
-    mech = gssint_get_mechanism(desired_mech);
1560d2b
+    status = gssint_select_mech_type(minor_status, desired_mech,
1560d2b
+				     &selected_mech);
1560d2b
+    if (status != GSS_S_COMPLETE)
1560d2b
+	return status;
1560d2b
+
1560d2b
+    mech = gssint_get_mechanism(selected_mech);
1560d2b
     if (!mech)
1560d2b
 	return GSS_S_BAD_MECH;
f1cb770
     else if (!mech->gss_acquire_cred_impersonate_name)
1560d2b
@@ -367,27 +374,26 @@ gss_add_cred_impersonate_name(OM_uint32 *minor_status,
1560d2b
 	internal_name = GSS_C_NO_NAME;
1560d2b
     } else {
1560d2b
 	union_cred = (gss_union_cred_t)input_cred_handle;
1560d2b
-	if (gssint_get_mechanism_cred(union_cred, desired_mech) !=
1560d2b
+	if (gssint_get_mechanism_cred(union_cred, selected_mech) !=
1560d2b
 	    GSS_C_NO_CREDENTIAL)
1560d2b
 	    return (GSS_S_DUPLICATE_ELEMENT);
1560d2b
     }
1560d2b
 
1560d2b
     mech_impersonator_cred =
1560d2b
 	gssint_get_mechanism_cred((gss_union_cred_t)impersonator_cred_handle,
1560d2b
-				  desired_mech);
1560d2b
+				  selected_mech);
1560d2b
     if (mech_impersonator_cred == GSS_C_NO_CREDENTIAL)
1560d2b
 	return (GSS_S_NO_CRED);
1560d2b
 
1560d2b
     /* may need to create a mechanism specific name */
1560d2b
     union_name = (gss_union_name_t)desired_name;
1560d2b
     if (union_name->mech_type &&
1560d2b
-	g_OID_equal(union_name->mech_type,
1560d2b
-		    &mech->mech_type))
1560d2b
+	g_OID_equal(union_name->mech_type, selected_mech))
1560d2b
 	internal_name = union_name->mech_name;
1560d2b
     else {
1560d2b
 	if (gssint_import_internal_name(minor_status,
1560d2b
-				        &mech->mech_type, union_name,
1560d2b
-				        &allocated_name) != GSS_S_COMPLETE)
1560d2b
+					selected_mech, union_name,
1560d2b
+					&allocated_name) != GSS_S_COMPLETE)
1560d2b
 	    return (GSS_S_BAD_NAME);
1560d2b
 	internal_name = allocated_name;
1560d2b
     }
1560d2b
@@ -402,11 +408,21 @@ gss_add_cred_impersonate_name(OM_uint32 *minor_status,
1560d2b
     else
1560d2b
 	time_req = 0;
1560d2b
 
1560d2b
+    status = gss_create_empty_oid_set(minor_status, &target_mechs);
1560d2b
+    if (status != GSS_S_COMPLETE)
1560d2b
+	goto errout;
1560d2b
+
1560d2b
+    status = gss_add_oid_set_member(minor_status,
1560d2b
+				    gssint_get_public_oid(selected_mech),
1560d2b
+				    &target_mechs);
1560d2b
+    if (status != GSS_S_COMPLETE)
1560d2b
+	goto errout;
1560d2b
+
1560d2b
     status = mech->gss_acquire_cred_impersonate_name(minor_status,
1560d2b
 						     mech_impersonator_cred,
1560d2b
 						     internal_name,
1560d2b
 						     time_req,
1560d2b
-						     GSS_C_NULL_OID_SET,
1560d2b
+						     target_mechs,
1560d2b
 						     cred_usage,
1560d2b
 						     &cred,
1560d2b
 						     NULL,
1560d2b
@@ -445,19 +461,15 @@ gss_add_cred_impersonate_name(OM_uint32 *minor_status,
1560d2b
 
1560d2b
     new_cred_array[union_cred->count] = cred;
1560d2b
     if ((new_mechs_array[union_cred->count].elements =
1560d2b
-	 malloc(mech->mech_type.length)) == NULL)
1560d2b
+	 malloc(selected_mech->length)) == NULL)
1560d2b
 	goto errout;
1560d2b
 
1560d2b
-    g_OID_copy(&new_mechs_array[union_cred->count],
1560d2b
-	       &mech->mech_type);
1560d2b
+    g_OID_copy(&new_mechs_array[union_cred->count], selected_mech);
1560d2b
 
1560d2b
     if (actual_mechs != NULL) {
1560d2b
-	gss_OID_set_desc oids;
1560d2b
-
1560d2b
-	oids.count = union_cred->count + 1;
1560d2b
-	oids.elements = new_mechs_array;
1560d2b
-
1560d2b
-	status = generic_gss_copy_oid_set(minor_status, &oids, actual_mechs);
1560d2b
+	status = gssint_make_public_oid_set(minor_status, new_mechs_array,
1560d2b
+					    union_cred->count + 1,
1560d2b
+					    actual_mechs);
1560d2b
 	if (GSS_ERROR(status)) {
1560d2b
 	    free(new_mechs_array[union_cred->count].elements);
1560d2b
 	    goto errout;
1560d2b
@@ -486,10 +498,12 @@ gss_add_cred_impersonate_name(OM_uint32 *minor_status,
1560d2b
     /* We're done with the internal name. Free it if we allocated it. */
1560d2b
 
1560d2b
     if (allocated_name)
1560d2b
-	(void) gssint_release_internal_name(&temp_minor_status,
1560d2b
-					   &mech->mech_type,
1560d2b
+	(void) gssint_release_internal_name(&temp_minor_status, selected_mech,
1560d2b
 					   &allocated_name);
1560d2b
 
1560d2b
+    if (target_mechs)
1560d2b
+	(void) gss_release_oid_set(&temp_minor_status, &target_mechs);
1560d2b
+
1560d2b
     return (GSS_S_COMPLETE);
1560d2b
 
1560d2b
 errout:
1560d2b
@@ -503,8 +517,10 @@ errout:
1560d2b
 
1560d2b
     if (allocated_name)
1560d2b
 	(void) gssint_release_internal_name(&temp_minor_status,
1560d2b
-					   &mech->mech_type,
1560d2b
-					   &allocated_name);
1560d2b
+					    selected_mech, &allocated_name);
1560d2b
+
1560d2b
+    if (target_mechs)
1560d2b
+	(void) gss_release_oid_set(&temp_minor_status, &target_mechs);
1560d2b
 
1560d2b
     if (input_cred_handle == GSS_C_NO_CREDENTIAL && union_cred)
1560d2b
 	free(union_cred);
1560d2b
diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c
ea319dd
index 07435d8..99e374f 100644
1560d2b
--- a/src/lib/gssapi/spnego/spnego_mech.c
1560d2b
+++ b/src/lib/gssapi/spnego/spnego_mech.c
ea319dd
@@ -2620,10 +2620,10 @@ spnego_gss_acquire_cred_impersonate_name(OM_uint32 *minor_status,
1560d2b
 					 gss_OID_set *actual_mechs,
1560d2b
 					 OM_uint32 *time_rec)
1560d2b
 {
1560d2b
-	OM_uint32 status;
1560d2b
+	OM_uint32 status, tmpmin;
1560d2b
 	gss_OID_set amechs = GSS_C_NULL_OID_SET;
1560d2b
 	spnego_gss_cred_id_t imp_spcred = NULL, out_spcred = NULL;
1560d2b
-	gss_cred_id_t imp_mcred, out_mcred;
1560d2b
+	gss_cred_id_t imp_mcred, out_mcred = GSS_C_NO_CREDENTIAL;
1560d2b
 
1560d2b
 	dsyslog("Entering spnego_gss_acquire_cred_impersonate_name\n");
1560d2b
 
ea319dd
@@ -2635,31 +2635,30 @@ spnego_gss_acquire_cred_impersonate_name(OM_uint32 *minor_status,
1560d2b
 
1560d2b
 	imp_spcred = (spnego_gss_cred_id_t)impersonator_cred_handle;
1560d2b
 	imp_mcred = imp_spcred ? imp_spcred->mcred : GSS_C_NO_CREDENTIAL;
1560d2b
-	if (desired_mechs == GSS_C_NO_OID_SET) {
1560d2b
-		status = gss_inquire_cred(minor_status, imp_mcred, NULL, NULL,
1560d2b
-					  NULL, &amechs);
1560d2b
-		if (status != GSS_S_COMPLETE)
1560d2b
-			return status;
1560d2b
-
1560d2b
-		desired_mechs = amechs;
1560d2b
-	}
1560d2b
+	status = gss_inquire_cred(minor_status, imp_mcred, NULL, NULL,
1560d2b
+				  NULL, &amechs);
1560d2b
+	if (status != GSS_S_COMPLETE)
1560d2b
+		return status;
1560d2b
 
1560d2b
 	status = gss_acquire_cred_impersonate_name(minor_status, imp_mcred,
1560d2b
 						   desired_name, time_req,
1560d2b
-						   desired_mechs, cred_usage,
1560d2b
+						   amechs, cred_usage,
1560d2b
 						   &out_mcred, actual_mechs,
1560d2b
 						   time_rec);
1560d2b
-
1560d2b
-	if (amechs != GSS_C_NULL_OID_SET)
1560d2b
-		(void) gss_release_oid_set(minor_status, &amechs);
1560d2b
+	if (status != GSS_S_COMPLETE)
1560d2b
+		goto cleanup;
1560d2b
 
1560d2b
 	status = create_spnego_cred(minor_status, out_mcred, &out_spcred);
1560d2b
-	if (status != GSS_S_COMPLETE) {
1560d2b
-		gss_release_cred(minor_status, &out_mcred);
1560d2b
-		return (status);
1560d2b
-	}
1560d2b
+	if (status != GSS_S_COMPLETE)
1560d2b
+		goto cleanup;
1560d2b
+
1560d2b
+	out_mcred = GSS_C_NO_CREDENTIAL;
1560d2b
 	*output_cred_handle = (gss_cred_id_t)out_spcred;
1560d2b
 
1560d2b
+cleanup:
1560d2b
+	(void) gss_release_oid_set(&tmpmin, &amechs);
1560d2b
+	(void) gss_release_cred(&tmpmin, &out_mcred);
1560d2b
+
1560d2b
 	dsyslog("Leaving spnego_gss_acquire_cred_impersonate_name\n");
1560d2b
 	return (status);
1560d2b
 }
1560d2b
-- 
ea319dd
2.9.3
1560d2b