gssapi: import bugfixes from Apple Heimdal-520
* check `ctx->gc_ctx` in `gss_inquire_context()` * check `gm_inquire_cred != NULL` in `gss_inquire_context()` * check `min_lifetime` in `gss_inquire_cred()` * check `gm_inquire_cred_by_mech != NULL` in `gss_inquire_cred_by_mech()` * set mech error in `gss_inquire_cred_by_oid()` * don't clobber error in `gss_inquire_cred_by_oid()` * don't pass NULL minor_status to `gss_krb5_free_lucid_sec_context()` * allow NULL ccache in `gss_krb5_ccache_name()` * NULL names OK in `_gss_find_mn()` * allow empty names in `gss_import_name()` (removes `input_name_buffer` length check). to support ANONYMOUS. in `gss_import_name()`, ignore mech name import failure as long as it's possible to import the name in some other mechanism * better argument validation in `gss_export_sec_context()` * in `gss_compare_name()`, check `mn2 != NULL` * check `gss_add_oid_set_member()` return code in `gss_indicate_mechs()` * in `gss_destroy_cred()`, set output cred handle to `GSS_C_NO_CREDENTIAL` * cast size_t to OM_uint32 where required
This commit is contained in:
		| @@ -60,7 +60,7 @@ gss_compare_name(OM_uint32 *minor_status, | |||||||
|  |  | ||||||
| 			major_status = _gss_find_mn(minor_status, name2, | 			major_status = _gss_find_mn(minor_status, name2, | ||||||
| 						    mn1->gmn_mech_oid, &mn2); | 						    mn1->gmn_mech_oid, &mn2); | ||||||
| 			if (major_status == GSS_S_COMPLETE) { | 			if (major_status == GSS_S_COMPLETE && mn2) { | ||||||
| 				return (mn1->gmn_mech->gm_compare_name( | 				return (mn1->gmn_mech->gm_compare_name( | ||||||
| 						minor_status, | 						minor_status, | ||||||
| 						mn1->gmn_name, | 						mn1->gmn_name, | ||||||
|   | |||||||
| @@ -158,7 +158,7 @@ gss_import_cred(OM_uint32 * minor_status, | |||||||
| 	    goto out; | 	    goto out; | ||||||
| 	} | 	} | ||||||
| 	oid.elements = data.data; | 	oid.elements = data.data; | ||||||
| 	oid.length = data.length; | 	oid.length = (OM_uint32)data.length; | ||||||
|  |  | ||||||
| 	m = __gss_get_mechanism(&oid); | 	m = __gss_get_mechanism(&oid); | ||||||
| 	krb5_data_free(&data); | 	krb5_data_free(&data); | ||||||
|   | |||||||
| @@ -43,6 +43,7 @@ gss_destroy_cred(void *status, | |||||||
| 	return GSS_S_COMPLETE; | 	return GSS_S_COMPLETE; | ||||||
|  |  | ||||||
|     cred = (struct _gss_cred *)*cred_handle; |     cred = (struct _gss_cred *)*cred_handle; | ||||||
|  |     *cred_handle = GSS_C_NO_CREDENTIAL; | ||||||
|  |  | ||||||
|     while (HEIM_SLIST_FIRST(&cred->gc_mc)) { |     while (HEIM_SLIST_FIRST(&cred->gc_mc)) { | ||||||
| 	mc = HEIM_SLIST_FIRST(&cred->gc_mc); | 	mc = HEIM_SLIST_FIRST(&cred->gc_mc); | ||||||
|   | |||||||
| @@ -38,7 +38,23 @@ gss_export_sec_context(OM_uint32 *minor_status, | |||||||
| 	gssapi_mech_interface m = ctx->gc_mech; | 	gssapi_mech_interface m = ctx->gc_mech; | ||||||
| 	gss_buffer_desc buf; | 	gss_buffer_desc buf; | ||||||
|  |  | ||||||
|  | 	*minor_status = 0; | ||||||
|  |  | ||||||
|  | 	if (interprocess_token) | ||||||
| 	    _mg_buffer_zero(interprocess_token); | 	    _mg_buffer_zero(interprocess_token); | ||||||
|  | 	else | ||||||
|  | 	    return GSS_S_CALL_INACCESSIBLE_READ; | ||||||
|  |  | ||||||
|  | 	if (context_handle == NULL) | ||||||
|  | 	    return GSS_S_NO_CONTEXT; | ||||||
|  |  | ||||||
|  | 	ctx = (struct _gss_context *) *context_handle; | ||||||
|  | 	if (ctx == NULL || ctx->gc_ctx == NULL) { | ||||||
|  | 	    *minor_status = 0; | ||||||
|  | 	    return GSS_S_NO_CONTEXT; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	m = ctx->gc_mech; | ||||||
|  |  | ||||||
| 	major_status = m->gm_export_sec_context(minor_status, | 	major_status = m->gm_export_sec_context(minor_status, | ||||||
| 	    &ctx->gc_ctx, &buf); | 	    &ctx->gc_ctx, &buf); | ||||||
|   | |||||||
| @@ -186,12 +186,14 @@ gss_import_name(OM_uint32 *minor_status, | |||||||
|         struct _gss_mech_switch	*m; |         struct _gss_mech_switch	*m; | ||||||
| 	gss_name_t		rname; | 	gss_name_t		rname; | ||||||
|  |  | ||||||
|  | 	if (input_name_buffer == GSS_C_NO_BUFFER) | ||||||
|  | 		return GSS_S_CALL_INACCESSIBLE_READ; | ||||||
|  | 	if (output_name == NULL) | ||||||
|  | 		return GSS_S_CALL_INACCESSIBLE_WRITE; | ||||||
|  |  | ||||||
| 	*output_name = GSS_C_NO_NAME; | 	*output_name = GSS_C_NO_NAME; | ||||||
|  |  | ||||||
| 	if (input_name_buffer->length == 0) { | 	/* Allow empty names since that's valid (ANONYMOUS for example) */ | ||||||
| 		*minor_status = 0; |  | ||||||
| 		return (GSS_S_BAD_NAME); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	_gss_load_mech(); | 	_gss_load_mech(); | ||||||
|  |  | ||||||
| @@ -261,7 +263,14 @@ gss_import_name(OM_uint32 *minor_status, | |||||||
| 		if (major_status != GSS_S_COMPLETE) { | 		if (major_status != GSS_S_COMPLETE) { | ||||||
| 			_gss_mg_error(&m->gm_mech, major_status, *minor_status); | 			_gss_mg_error(&m->gm_mech, major_status, *minor_status); | ||||||
| 			free(mn); | 			free(mn); | ||||||
| 			goto out; | 			/** | ||||||
|  | 			 * If we failed to import the name in a mechanism, it | ||||||
|  | 			 * will be ignored as long as its possible to import | ||||||
|  | 			 * name in some other mechanism. We will catch the | ||||||
|  | 			 * failure later though in gss_init_sec_context() or | ||||||
|  | 			 * another function. | ||||||
|  | 			 */ | ||||||
|  | 			continue; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		mn->gmn_mech = &m->gm_mech; | 		mn->gmn_mech = &m->gm_mech; | ||||||
|   | |||||||
| @@ -33,7 +33,7 @@ gss_indicate_mechs(OM_uint32 *minor_status, | |||||||
|     gss_OID_set *mech_set) |     gss_OID_set *mech_set) | ||||||
| { | { | ||||||
| 	struct _gss_mech_switch *m; | 	struct _gss_mech_switch *m; | ||||||
| 	OM_uint32 major_status; | 	OM_uint32 major_status, junk; | ||||||
| 	gss_OID_set set; | 	gss_OID_set set; | ||||||
| 	size_t i; | 	size_t i; | ||||||
|  |  | ||||||
| @@ -50,16 +50,25 @@ gss_indicate_mechs(OM_uint32 *minor_status, | |||||||
| 			    minor_status, &set); | 			    minor_status, &set); | ||||||
| 			if (major_status) | 			if (major_status) | ||||||
| 				continue; | 				continue; | ||||||
| 			for (i = 0; i < set->count; i++) | 			major_status = GSS_S_COMPLETE; | ||||||
| 				gss_add_oid_set_member( | 			for (i = 0; i < set->count; i++) { | ||||||
|  | 				major_status = gss_add_oid_set_member( | ||||||
| 				    minor_status, &set->elements[i], mech_set); | 				    minor_status, &set->elements[i], mech_set); | ||||||
|  | 				if (major_status) | ||||||
|  | 					break; | ||||||
|  | 			} | ||||||
| 			gss_release_oid_set(minor_status, &set); | 			gss_release_oid_set(minor_status, &set); | ||||||
| 		} else { | 		} else { | ||||||
| 			gss_add_oid_set_member( | 			major_status = gss_add_oid_set_member( | ||||||
| 			    minor_status, m->gm_mech_oid, mech_set); | 			    minor_status, m->gm_mech_oid, mech_set); | ||||||
| 		} | 		} | ||||||
|  | 		if (major_status) | ||||||
|  | 			break; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if (major_status) | ||||||
|  | 		gss_release_oid_set(&junk, mech_set); | ||||||
|  |  | ||||||
| 	*minor_status = 0; | 	*minor_status = 0; | ||||||
| 	return (GSS_S_COMPLETE); | 	return major_status; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -41,7 +41,7 @@ gss_inquire_context(OM_uint32 *minor_status, | |||||||
| { | { | ||||||
| 	OM_uint32 major_status; | 	OM_uint32 major_status; | ||||||
| 	struct _gss_context *ctx = (struct _gss_context *) context_handle; | 	struct _gss_context *ctx = (struct _gss_context *) context_handle; | ||||||
| 	gssapi_mech_interface m = ctx->gc_mech; | 	gssapi_mech_interface m; | ||||||
| 	struct _gss_name *name; | 	struct _gss_name *name; | ||||||
| 	gss_name_t src_mn, targ_mn; | 	gss_name_t src_mn, targ_mn; | ||||||
|  |  | ||||||
| @@ -60,6 +60,13 @@ gss_inquire_context(OM_uint32 *minor_status, | |||||||
| 	    *mech_type = GSS_C_NO_OID; | 	    *mech_type = GSS_C_NO_OID; | ||||||
| 	src_mn = targ_mn = GSS_C_NO_NAME; | 	src_mn = targ_mn = GSS_C_NO_NAME; | ||||||
|  |  | ||||||
|  | 	if (ctx == NULL || ctx->gc_ctx == NULL) { | ||||||
|  | 	    *minor_status = 0; | ||||||
|  | 	    return GSS_S_NO_CONTEXT; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	m = ctx->gc_mech; | ||||||
|  |  | ||||||
| 	major_status = m->gm_inquire_context(minor_status, | 	major_status = m->gm_inquire_context(minor_status, | ||||||
| 	    ctx->gc_ctx, | 	    ctx->gc_ctx, | ||||||
| 	    src_name ? &src_mn : NULL, | 	    src_name ? &src_mn : NULL, | ||||||
|   | |||||||
| @@ -100,6 +100,9 @@ gss_inquire_cred(OM_uint32 *minor_status, | |||||||
| 			gss_name_t mc_name; | 			gss_name_t mc_name; | ||||||
| 			OM_uint32 mc_lifetime; | 			OM_uint32 mc_lifetime; | ||||||
|  |  | ||||||
|  | 			if (mc->gmc_mech->gm_inquire_cred == NULL) | ||||||
|  | 				continue; | ||||||
|  |  | ||||||
| 			major_status = mc->gmc_mech->gm_inquire_cred(minor_status, | 			major_status = mc->gmc_mech->gm_inquire_cred(minor_status, | ||||||
| 			    mc->gmc_cred, &mc_name, &mc_lifetime, &usage, NULL); | 			    mc->gmc_cred, &mc_name, &mc_lifetime, &usage, NULL); | ||||||
| 			if (major_status) | 			if (major_status) | ||||||
| @@ -135,6 +138,9 @@ gss_inquire_cred(OM_uint32 *minor_status, | |||||||
| 			gss_name_t mc_name; | 			gss_name_t mc_name; | ||||||
| 			OM_uint32 mc_lifetime; | 			OM_uint32 mc_lifetime; | ||||||
|  |  | ||||||
|  | 			if (m->gm_mech.gm_inquire_cred == NULL) | ||||||
|  | 				continue; | ||||||
|  |  | ||||||
| 			major_status = m->gm_mech.gm_inquire_cred(minor_status, | 			major_status = m->gm_mech.gm_inquire_cred(minor_status, | ||||||
| 			    GSS_C_NO_CREDENTIAL, &mc_name, &mc_lifetime, | 			    GSS_C_NO_CREDENTIAL, &mc_name, &mc_lifetime, | ||||||
| 			    &usage, NULL); | 			    &usage, NULL); | ||||||
| @@ -169,12 +175,15 @@ gss_inquire_cred(OM_uint32 *minor_status, | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (found == 0) { | 	if (found == 0 || min_lifetime == 0) { | ||||||
| 		gss_name_t n = (gss_name_t)name; | 		gss_name_t n = (gss_name_t)name; | ||||||
| 		if (n) | 		if (n) | ||||||
| 			gss_release_name(minor_status, &n); | 			gss_release_name(minor_status, &n); | ||||||
| 		gss_release_oid_set(minor_status, mechanisms); | 		gss_release_oid_set(minor_status, mechanisms); | ||||||
| 		*minor_status = 0; | 		*minor_status = 0; | ||||||
|  | 		if (min_lifetime == 0) | ||||||
|  | 			return (GSS_S_CREDENTIALS_EXPIRED); | ||||||
|  |  | ||||||
| 		return (GSS_S_NO_CRED); | 		return (GSS_S_NO_CRED); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -55,7 +55,7 @@ gss_inquire_cred_by_mech(OM_uint32 *minor_status, | |||||||
| 	    *cred_usage = 0; | 	    *cred_usage = 0; | ||||||
|  |  | ||||||
| 	m = __gss_get_mechanism(mech_type); | 	m = __gss_get_mechanism(mech_type); | ||||||
| 	if (!m) | 	if (m == NULL || m->gm_inquire_cred_by_mech == NULL) | ||||||
| 		return (GSS_S_NO_CRED); | 		return (GSS_S_NO_CRED); | ||||||
|  |  | ||||||
| 	if (cred_handle != GSS_C_NO_CREDENTIAL) { | 	if (cred_handle != GSS_C_NO_CREDENTIAL) { | ||||||
|   | |||||||
| @@ -50,6 +50,8 @@ gss_inquire_cred_by_oid (OM_uint32 *minor_status, | |||||||
| 	if (cred == NULL) | 	if (cred == NULL) | ||||||
| 		return GSS_S_NO_CRED; | 		return GSS_S_NO_CRED; | ||||||
|  |  | ||||||
|  | 	status = GSS_S_FAILURE; | ||||||
|  |  | ||||||
| 	HEIM_SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { | 	HEIM_SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { | ||||||
| 		gss_buffer_set_t rset = GSS_C_NO_BUFFER_SET; | 		gss_buffer_set_t rset = GSS_C_NO_BUFFER_SET; | ||||||
| 		size_t i; | 		size_t i; | ||||||
| @@ -66,10 +68,12 @@ gss_inquire_cred_by_oid (OM_uint32 *minor_status, | |||||||
|  |  | ||||||
| 		status = m->gm_inquire_cred_by_oid(minor_status, | 		status = m->gm_inquire_cred_by_oid(minor_status, | ||||||
| 		    mc->gmc_cred, desired_object, &rset); | 		    mc->gmc_cred, desired_object, &rset); | ||||||
| 		if (status != GSS_S_COMPLETE) | 		if (status != GSS_S_COMPLETE) { | ||||||
|  | 			_gss_mg_error(m, status, *minor_status); | ||||||
| 			continue; | 			continue; | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		for (i = 0; i < rset->count; i++) { | 		for (i = 0; rset != NULL && i < rset->count; i++) { | ||||||
| 			status = gss_add_buffer_set_member(minor_status, | 			status = gss_add_buffer_set_member(minor_status, | ||||||
| 			     &rset->elements[i], &set); | 			     &rset->elements[i], &set); | ||||||
| 			if (status != GSS_S_COMPLETE) | 			if (status != GSS_S_COMPLETE) | ||||||
| @@ -77,7 +81,7 @@ gss_inquire_cred_by_oid (OM_uint32 *minor_status, | |||||||
| 		} | 		} | ||||||
| 		gss_release_buffer_set(minor_status, &rset); | 		gss_release_buffer_set(minor_status, &rset); | ||||||
| 	} | 	} | ||||||
| 	if (set == GSS_C_NO_BUFFER_SET) | 	if (set == GSS_C_NO_BUFFER_SET && status == GSS_S_COMPLETE) | ||||||
| 		status = GSS_S_FAILURE; | 		status = GSS_S_FAILURE; | ||||||
| 	*data_set = set; | 	*data_set = set; | ||||||
| 	*minor_status = 0; | 	*minor_status = 0; | ||||||
|   | |||||||
| @@ -390,8 +390,9 @@ out: | |||||||
| 	krb5_free_context(context); | 	krb5_free_context(context); | ||||||
|  |  | ||||||
|     if (ret) { |     if (ret) { | ||||||
|  | 	OM_uint32 junk; | ||||||
| 	if (ctx) | 	if (ctx) | ||||||
| 	    gss_krb5_free_lucid_sec_context(NULL, ctx); | 	    gss_krb5_free_lucid_sec_context(&junk, ctx); | ||||||
|  |  | ||||||
| 	*minor_status = ret; | 	*minor_status = ret; | ||||||
| 	return GSS_S_FAILURE; | 	return GSS_S_FAILURE; | ||||||
| @@ -527,8 +528,12 @@ gss_krb5_ccache_name(OM_uint32 *minor_status, | |||||||
|     if (out_name) |     if (out_name) | ||||||
| 	*out_name = NULL; | 	*out_name = NULL; | ||||||
|  |  | ||||||
|  |     if (name) { | ||||||
| 	buffer.value = rk_UNCONST(name); | 	buffer.value = rk_UNCONST(name); | ||||||
| 	buffer.length = strlen(name); | 	buffer.length = strlen(name); | ||||||
|  |     } else { | ||||||
|  | 	_mg_buffer_zero(&buffer); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     HEIM_SLIST_FOREACH(m, &_gss_mechs, gm_link) { |     HEIM_SLIST_FOREACH(m, &_gss_mechs, gm_link) { | ||||||
| 	if (m->gm_mech.gm_set_sec_context_option == NULL) | 	if (m->gm_mech.gm_set_sec_context_option == NULL) | ||||||
| @@ -642,7 +647,7 @@ gsskrb5_extract_authz_data_from_sec_context(OM_uint32 *minor_status, | |||||||
|  |  | ||||||
|     oid.components[oid.length - 1] = ad_type; |     oid.components[oid.length - 1] = ad_type; | ||||||
|  |  | ||||||
|     oid_flat.length = der_length_oid(&oid); |     oid_flat.length = (OM_uint32)der_length_oid(&oid); | ||||||
|     oid_flat.elements = malloc(oid_flat.length); |     oid_flat.elements = malloc(oid_flat.length); | ||||||
|     if (oid_flat.elements == NULL) { |     if (oid_flat.elements == NULL) { | ||||||
| 	free(oid.components); | 	free(oid.components); | ||||||
|   | |||||||
| @@ -37,7 +37,18 @@ gss_unwrap(OM_uint32 *minor_status, | |||||||
|     gss_qop_t *qop_state) |     gss_qop_t *qop_state) | ||||||
| { | { | ||||||
| 	struct _gss_context *ctx = (struct _gss_context *) context_handle; | 	struct _gss_context *ctx = (struct _gss_context *) context_handle; | ||||||
| 	gssapi_mech_interface m = ctx->gc_mech; | 	gssapi_mech_interface m; | ||||||
|  |  | ||||||
|  | 	if (conf_state) | ||||||
|  | 	    *conf_state = 0; | ||||||
|  | 	if (qop_state) | ||||||
|  | 	    *qop_state = 0; | ||||||
|  |  | ||||||
|  | 	if (ctx == NULL) { | ||||||
|  | 	    *minor_status = 0; | ||||||
|  | 	    return GSS_S_NO_CONTEXT; | ||||||
|  | 	} | ||||||
|  | 	m = ctx->gc_mech; | ||||||
|  |  | ||||||
| 	return (m->gm_unwrap(minor_status, ctx->gc_ctx, | 	return (m->gm_unwrap(minor_status, ctx->gc_ctx, | ||||||
| 		    input_message_buffer, output_message_buffer, | 		    input_message_buffer, output_message_buffer, | ||||||
|   | |||||||
| @@ -30,7 +30,8 @@ | |||||||
|  |  | ||||||
| static OM_uint32 | static OM_uint32 | ||||||
| _gss_copy_oid(OM_uint32 *minor_status, | _gss_copy_oid(OM_uint32 *minor_status, | ||||||
|     gss_const_OID from_oid, gss_OID to_oid) | 	      gss_const_OID from_oid, | ||||||
|  | 	      gss_OID to_oid) | ||||||
| { | { | ||||||
| 	size_t len = from_oid->length; | 	size_t len = from_oid->length; | ||||||
|  |  | ||||||
| @@ -41,7 +42,7 @@ _gss_copy_oid(OM_uint32 *minor_status, | |||||||
| 		*minor_status = ENOMEM; | 		*minor_status = ENOMEM; | ||||||
| 		return GSS_S_FAILURE; | 		return GSS_S_FAILURE; | ||||||
| 	} | 	} | ||||||
| 	to_oid->length = len; | 	to_oid->length = (OM_uint32)len; | ||||||
| 	memcpy(to_oid->elements, from_oid->elements, len); | 	memcpy(to_oid->elements, from_oid->elements, len); | ||||||
| 	return (GSS_S_COMPLETE); | 	return (GSS_S_COMPLETE); | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Luke Howard
					Luke Howard