17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5ba7b222eSGlenn Barry  * Common Development and Distribution License (the "License").
6ba7b222eSGlenn Barry  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
225e01956fSGlenn Barry  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate /*
267c478bd9Sstevel@tonic-gate  *  glue routine for gss_accept_sec_context
277c478bd9Sstevel@tonic-gate  */
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #include <mechglueP.h>
305e01956fSGlenn Barry #include "gssapiP_generic.h"
317c478bd9Sstevel@tonic-gate #ifdef HAVE_STDLIB_H
327c478bd9Sstevel@tonic-gate #include <stdlib.h>
337c478bd9Sstevel@tonic-gate #endif
347c478bd9Sstevel@tonic-gate #include <string.h>
357c478bd9Sstevel@tonic-gate #include <errno.h>
365e01956fSGlenn Barry #include <syslog.h>
377c478bd9Sstevel@tonic-gate 
385e01956fSGlenn Barry #ifndef LEAN_CLIENT
39503a2b89SPeter Shoults static OM_uint32
val_acc_sec_ctx_args(OM_uint32 * minor_status,gss_ctx_id_t * context_handle,gss_buffer_t input_token_buffer,gss_name_t * src_name,gss_OID * mech_type,gss_buffer_t output_token,gss_cred_id_t * d_cred)40503a2b89SPeter Shoults val_acc_sec_ctx_args(
41503a2b89SPeter Shoults 	OM_uint32 *minor_status,
42503a2b89SPeter Shoults 	gss_ctx_id_t *context_handle,
43503a2b89SPeter Shoults 	gss_buffer_t input_token_buffer,
44503a2b89SPeter Shoults 	gss_name_t *src_name,
45503a2b89SPeter Shoults 	gss_OID *mech_type,
46503a2b89SPeter Shoults 	gss_buffer_t output_token,
47503a2b89SPeter Shoults 	gss_cred_id_t *d_cred)
48503a2b89SPeter Shoults {
49503a2b89SPeter Shoults 
50503a2b89SPeter Shoults 	/* Initialize outputs. */
51503a2b89SPeter Shoults 
52503a2b89SPeter Shoults 	if (minor_status != NULL)
53503a2b89SPeter Shoults 		*minor_status = 0;
54503a2b89SPeter Shoults 
55503a2b89SPeter Shoults 	if (src_name != NULL)
56503a2b89SPeter Shoults 		*src_name = GSS_C_NO_NAME;
57503a2b89SPeter Shoults 
58503a2b89SPeter Shoults 	if (mech_type != NULL)
59503a2b89SPeter Shoults 		*mech_type = GSS_C_NO_OID;
60503a2b89SPeter Shoults 
61503a2b89SPeter Shoults 	if (output_token != GSS_C_NO_BUFFER) {
62503a2b89SPeter Shoults 		output_token->length = 0;
63503a2b89SPeter Shoults 		output_token->value = NULL;
64503a2b89SPeter Shoults 	}
65503a2b89SPeter Shoults 
66503a2b89SPeter Shoults 	if (d_cred != NULL)
67503a2b89SPeter Shoults 		*d_cred = GSS_C_NO_CREDENTIAL;
68503a2b89SPeter Shoults 
69503a2b89SPeter Shoults 	/* Validate arguments. */
70503a2b89SPeter Shoults 
71503a2b89SPeter Shoults 	if (minor_status == NULL)
72503a2b89SPeter Shoults 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
73503a2b89SPeter Shoults 
74503a2b89SPeter Shoults 	if (context_handle == NULL)
75503a2b89SPeter Shoults 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
76503a2b89SPeter Shoults 
77503a2b89SPeter Shoults 	if (input_token_buffer == GSS_C_NO_BUFFER)
78503a2b89SPeter Shoults 		return (GSS_S_CALL_INACCESSIBLE_READ);
79503a2b89SPeter Shoults 
80503a2b89SPeter Shoults 	if (output_token == GSS_C_NO_BUFFER)
81503a2b89SPeter Shoults 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
82503a2b89SPeter Shoults 
83503a2b89SPeter Shoults 	return (GSS_S_COMPLETE);
84503a2b89SPeter Shoults }
85503a2b89SPeter Shoults 
867c478bd9Sstevel@tonic-gate OM_uint32
gss_accept_sec_context(minor_status,context_handle,verifier_cred_handle,input_token_buffer,input_chan_bindings,src_name,mech_type,output_token,ret_flags,time_rec,d_cred)877c478bd9Sstevel@tonic-gate gss_accept_sec_context(minor_status,
887c478bd9Sstevel@tonic-gate 			context_handle,
897c478bd9Sstevel@tonic-gate 			verifier_cred_handle,
907c478bd9Sstevel@tonic-gate 			input_token_buffer,
917c478bd9Sstevel@tonic-gate 			input_chan_bindings,
927c478bd9Sstevel@tonic-gate 			src_name,
937c478bd9Sstevel@tonic-gate 			mech_type,
947c478bd9Sstevel@tonic-gate 			output_token,
957c478bd9Sstevel@tonic-gate 			ret_flags,
967c478bd9Sstevel@tonic-gate 			time_rec,
977c478bd9Sstevel@tonic-gate 			d_cred)
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate OM_uint32 			*minor_status;
1007c478bd9Sstevel@tonic-gate gss_ctx_id_t			*context_handle;
1017c478bd9Sstevel@tonic-gate const gss_cred_id_t		verifier_cred_handle;
1027c478bd9Sstevel@tonic-gate const gss_buffer_t		input_token_buffer;
1037c478bd9Sstevel@tonic-gate const gss_channel_bindings_t	input_chan_bindings;
1047c478bd9Sstevel@tonic-gate gss_name_t			*src_name;
1057c478bd9Sstevel@tonic-gate gss_OID				*mech_type;
1067c478bd9Sstevel@tonic-gate gss_buffer_t			output_token;
1077c478bd9Sstevel@tonic-gate OM_uint32			*ret_flags;
1087c478bd9Sstevel@tonic-gate OM_uint32			*time_rec;
1097c478bd9Sstevel@tonic-gate gss_cred_id_t			*d_cred; /* delegated cred handle */
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate {
112354d1447Swyllys 	OM_uint32		status, temp_status, t_minstat;
1137c478bd9Sstevel@tonic-gate 	gss_union_ctx_id_t	union_ctx_id;
1147c478bd9Sstevel@tonic-gate 	gss_union_cred_t	union_cred;
1157c478bd9Sstevel@tonic-gate 	gss_cred_id_t	input_cred_handle = GSS_C_NO_CREDENTIAL;
1167c478bd9Sstevel@tonic-gate 	gss_cred_id_t	tmp_d_cred = GSS_C_NO_CREDENTIAL;
1177c478bd9Sstevel@tonic-gate 	gss_name_t		internal_name = GSS_C_NO_NAME;
1187c478bd9Sstevel@tonic-gate 	gss_name_t		tmp_src_name = GSS_C_NO_NAME;
1197c478bd9Sstevel@tonic-gate 	gss_OID_desc	token_mech_type_desc;
1207c478bd9Sstevel@tonic-gate 	gss_OID		token_mech_type = &token_mech_type_desc;
121354d1447Swyllys 	OM_uint32	flags;
1227c478bd9Sstevel@tonic-gate 	gss_mechanism	mech;
1237c478bd9Sstevel@tonic-gate 
124503a2b89SPeter Shoults 	status = val_acc_sec_ctx_args(minor_status,
125503a2b89SPeter Shoults 				context_handle,
126503a2b89SPeter Shoults 				input_token_buffer,
127503a2b89SPeter Shoults 				src_name,
128503a2b89SPeter Shoults 				mech_type,
129503a2b89SPeter Shoults 				output_token,
130503a2b89SPeter Shoults 				d_cred);
131503a2b89SPeter Shoults 	if (status != GSS_S_COMPLETE)
132503a2b89SPeter Shoults 		return (status);
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	/*
1357c478bd9Sstevel@tonic-gate 	 * if context_handle is GSS_C_NO_CONTEXT, allocate a union context
1367c478bd9Sstevel@tonic-gate 	 * descriptor to hold the mech type information as well as the
1377c478bd9Sstevel@tonic-gate 	 * underlying mechanism context handle. Otherwise, cast the
1387c478bd9Sstevel@tonic-gate 	 * value of *context_handle to the union context variable.
1397c478bd9Sstevel@tonic-gate 	 */
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	if (*context_handle == GSS_C_NO_CONTEXT) {
1427c478bd9Sstevel@tonic-gate 
143ba7b222eSGlenn Barry 		if (input_token_buffer == GSS_C_NO_BUFFER)
1447c478bd9Sstevel@tonic-gate 			return (GSS_S_CALL_INACCESSIBLE_READ);
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 		/* Get the token mech type */
1477c478bd9Sstevel@tonic-gate 		status = __gss_get_mech_type(token_mech_type,
1487c478bd9Sstevel@tonic-gate 					input_token_buffer);
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 		if (status)
1517c478bd9Sstevel@tonic-gate 			return (status);
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 		status = GSS_S_FAILURE;
1547c478bd9Sstevel@tonic-gate 		union_ctx_id = (gss_union_ctx_id_t)
1557c478bd9Sstevel@tonic-gate 			malloc(sizeof (gss_union_ctx_id_desc));
1567c478bd9Sstevel@tonic-gate 		if (!union_ctx_id)
1577c478bd9Sstevel@tonic-gate 			return (GSS_S_FAILURE);
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 		union_ctx_id->internal_ctx_id = GSS_C_NO_CONTEXT;
160354d1447Swyllys 		status = generic_gss_copy_oid(&t_minstat,
1617c478bd9Sstevel@tonic-gate 					token_mech_type,
1627c478bd9Sstevel@tonic-gate 					&union_ctx_id->mech_type);
1637c478bd9Sstevel@tonic-gate 		if (status != GSS_S_COMPLETE) {
1647c478bd9Sstevel@tonic-gate 			free(union_ctx_id);
1657c478bd9Sstevel@tonic-gate 			return (status);
1667c478bd9Sstevel@tonic-gate 		}
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 		/* set the new context handle to caller's data */
1697c478bd9Sstevel@tonic-gate 		*context_handle = (gss_ctx_id_t)union_ctx_id;
1707c478bd9Sstevel@tonic-gate 	} else {
1717c478bd9Sstevel@tonic-gate 		union_ctx_id = (gss_union_ctx_id_t)*context_handle;
1727c478bd9Sstevel@tonic-gate 		token_mech_type = union_ctx_id->mech_type;
1737c478bd9Sstevel@tonic-gate 	}
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 	/*
1767c478bd9Sstevel@tonic-gate 	 * get the appropriate cred handle from the union cred struct.
1777c478bd9Sstevel@tonic-gate 	 * defaults to GSS_C_NO_CREDENTIAL if there is no cred, which will
1787c478bd9Sstevel@tonic-gate 	 * use the default credential.
1797c478bd9Sstevel@tonic-gate 	 */
1807c478bd9Sstevel@tonic-gate 	union_cred = (gss_union_cred_t)verifier_cred_handle;
1817c478bd9Sstevel@tonic-gate 	input_cred_handle = __gss_get_mechanism_cred(union_cred,
1827c478bd9Sstevel@tonic-gate 						token_mech_type);
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 	/*
1857c478bd9Sstevel@tonic-gate 	 * now select the approprate underlying mechanism routine and
1867c478bd9Sstevel@tonic-gate 	 * call it.
1877c478bd9Sstevel@tonic-gate 	 */
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 	mech = __gss_get_mechanism(token_mech_type);
1907c478bd9Sstevel@tonic-gate 	if (mech && mech->gss_accept_sec_context) {
1917c478bd9Sstevel@tonic-gate 		status = mech->gss_accept_sec_context(
1927c478bd9Sstevel@tonic-gate 					mech->context,
1937c478bd9Sstevel@tonic-gate 					minor_status,
1947c478bd9Sstevel@tonic-gate 					&union_ctx_id->internal_ctx_id,
1957c478bd9Sstevel@tonic-gate 					input_cred_handle,
1967c478bd9Sstevel@tonic-gate 					input_token_buffer,
1977c478bd9Sstevel@tonic-gate 					input_chan_bindings,
1987c478bd9Sstevel@tonic-gate 					&internal_name,
1995e01956fSGlenn Barry 					mech_type,
2007c478bd9Sstevel@tonic-gate 					output_token,
201354d1447Swyllys 					&flags,
2027c478bd9Sstevel@tonic-gate 					time_rec,
2037c478bd9Sstevel@tonic-gate 					d_cred ? &tmp_d_cred : NULL);
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate 		/* If there's more work to do, keep going... */
2067c478bd9Sstevel@tonic-gate 		if (status == GSS_S_CONTINUE_NEEDED)
2077c478bd9Sstevel@tonic-gate 			return (GSS_S_CONTINUE_NEEDED);
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 		/* if the call failed, return with failure */
2105e01956fSGlenn Barry 		if (status != GSS_S_COMPLETE) {
2115e01956fSGlenn Barry 			if (mech_type && (*mech_type != GSS_C_NULL_OID))
2125e01956fSGlenn Barry 				map_error_oid(minor_status, *mech_type);
2135e01956fSGlenn Barry 			else {
2145e01956fSGlenn Barry 				map_error(minor_status, mech);
2155e01956fSGlenn Barry 			}
2167c478bd9Sstevel@tonic-gate 			goto error_out;
2175e01956fSGlenn Barry 		}
2187c478bd9Sstevel@tonic-gate 
219354d1447Swyllys 
2207c478bd9Sstevel@tonic-gate 		/*
2217c478bd9Sstevel@tonic-gate 		 * if src_name is non-NULL,
2227c478bd9Sstevel@tonic-gate 		 * convert internal_name into a union name equivalent
2237c478bd9Sstevel@tonic-gate 		 * First call the mechanism specific display_name()
2247c478bd9Sstevel@tonic-gate 		 * then call gss_import_name() to create
2257c478bd9Sstevel@tonic-gate 		 * the union name struct cast to src_name
226*4aed303fSChris Love 		 * NB: __gss_convert_name_to_union_name will
227*4aed303fSChris Love 		 * "consume" (free) the name.
2287c478bd9Sstevel@tonic-gate 		 */
2297c478bd9Sstevel@tonic-gate 		if (internal_name != NULL) {
2307c478bd9Sstevel@tonic-gate 			temp_status = __gss_convert_name_to_union_name(
231354d1447Swyllys 				&t_minstat, mech,
2327c478bd9Sstevel@tonic-gate 				internal_name, &tmp_src_name);
2337c478bd9Sstevel@tonic-gate 			if (temp_status != GSS_S_COMPLETE) {
234354d1447Swyllys 				*minor_status = t_minstat;
2355e01956fSGlenn Barry 				map_error(minor_status, mech);
2367c478bd9Sstevel@tonic-gate 				if (output_token->length)
2377c478bd9Sstevel@tonic-gate 					(void) gss_release_buffer(
238354d1447Swyllys 						&t_minstat,
2397c478bd9Sstevel@tonic-gate 						output_token);
2407c478bd9Sstevel@tonic-gate 				return (temp_status);
2417c478bd9Sstevel@tonic-gate 			}
2427c478bd9Sstevel@tonic-gate 			if (src_name != NULL) {
2437c478bd9Sstevel@tonic-gate 				*src_name = tmp_src_name;
2447c478bd9Sstevel@tonic-gate 			}
2457c478bd9Sstevel@tonic-gate 		} else if (src_name != NULL) {
2467c478bd9Sstevel@tonic-gate 			*src_name = GSS_C_NO_NAME;
2477c478bd9Sstevel@tonic-gate 		}
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate 		/* Ensure we're returning correct creds format */
250354d1447Swyllys 		if ((flags & GSS_C_DELEG_FLAG) &&
251354d1447Swyllys 		    tmp_d_cred != GSS_C_NO_CREDENTIAL) {
252354d1447Swyllys 			/*
253354d1447Swyllys 			 * If we got back an OID different from the original
254354d1447Swyllys 			 * token OID, assume the delegated_cred is already
255354d1447Swyllys 			 * a proper union_cred and just return it.  Don't
256354d1447Swyllys 			 * try to re-wrap it.  This is for SPNEGO or other
257354d1447Swyllys 			 * pseudo-mechanisms.
258354d1447Swyllys 			 */
2595e01956fSGlenn Barry 			if (*mech_type != GSS_C_NO_OID &&
260354d1447Swyllys 			    token_mech_type != GSS_C_NO_OID &&
2615e01956fSGlenn Barry 			    !g_OID_equal(*mech_type, token_mech_type)) {
262354d1447Swyllys 				*d_cred = tmp_d_cred;
263354d1447Swyllys 			} else {
264354d1447Swyllys 				gss_union_cred_t d_u_cred = NULL;
2657c478bd9Sstevel@tonic-gate 
266354d1447Swyllys 				d_u_cred = malloc(sizeof (gss_union_cred_desc));
267354d1447Swyllys 				if (d_u_cred == NULL) {
268354d1447Swyllys 					status = GSS_S_FAILURE;
269354d1447Swyllys 					goto error_out;
270354d1447Swyllys 				}
271354d1447Swyllys 				(void) memset(d_u_cred, 0,
272354d1447Swyllys 					    sizeof (gss_union_cred_desc));
2737c478bd9Sstevel@tonic-gate 
274354d1447Swyllys 				d_u_cred->count = 1;
2757c478bd9Sstevel@tonic-gate 
276354d1447Swyllys 				status = generic_gss_copy_oid(
277354d1447Swyllys 					&t_minstat,
2785e01956fSGlenn Barry 					*mech_type,
279354d1447Swyllys 					&d_u_cred->mechs_array);
2807c478bd9Sstevel@tonic-gate 
281354d1447Swyllys 				if (status != GSS_S_COMPLETE) {
282354d1447Swyllys 					free(d_u_cred);
283354d1447Swyllys 					goto error_out;
284354d1447Swyllys 				}
2857c478bd9Sstevel@tonic-gate 
286354d1447Swyllys 				d_u_cred->cred_array = malloc(
287354d1447Swyllys 						sizeof (gss_cred_id_t));
288354d1447Swyllys 				if (d_u_cred->cred_array != NULL) {
289354d1447Swyllys 					d_u_cred->cred_array[0] = tmp_d_cred;
290354d1447Swyllys 				} else {
291354d1447Swyllys 					free(d_u_cred);
292354d1447Swyllys 					status = GSS_S_FAILURE;
293354d1447Swyllys 					goto error_out;
294354d1447Swyllys 				}
2957c478bd9Sstevel@tonic-gate 
296354d1447Swyllys 				if (status != GSS_S_COMPLETE) {
297354d1447Swyllys 					free(d_u_cred->cred_array);
298354d1447Swyllys 					free(d_u_cred);
299354d1447Swyllys 					goto error_out;
300354d1447Swyllys 				}
3017c478bd9Sstevel@tonic-gate 
302354d1447Swyllys 				internal_name = GSS_C_NO_NAME;
3037c478bd9Sstevel@tonic-gate 
304354d1447Swyllys 				d_u_cred->auxinfo.creation_time = time(0);
305354d1447Swyllys 				d_u_cred->auxinfo.time_rec = 0;
3067c478bd9Sstevel@tonic-gate 
307354d1447Swyllys 				if (mech->gss_inquire_cred) {
308354d1447Swyllys 					status = mech->gss_inquire_cred(
309354d1447Swyllys 						mech->context,
310354d1447Swyllys 						minor_status,
311354d1447Swyllys 						tmp_d_cred,
312354d1447Swyllys 						&internal_name,
313354d1447Swyllys 						&d_u_cred->auxinfo.time_rec,
314354d1447Swyllys 						&d_u_cred->auxinfo.cred_usage,
315354d1447Swyllys 						NULL);
3167c478bd9Sstevel@tonic-gate 				}
3177c478bd9Sstevel@tonic-gate 
3185e01956fSGlenn Barry 				if (status != GSS_S_COMPLETE)
3195e01956fSGlenn Barry 					map_error(minor_status, mech);
3205e01956fSGlenn Barry 
321354d1447Swyllys 				if (internal_name != NULL) {
322354d1447Swyllys 					temp_status =
323354d1447Swyllys 					    __gss_convert_name_to_union_name(
324354d1447Swyllys 						&t_minstat, mech,
325354d1447Swyllys 						internal_name, &tmp_src_name);
326354d1447Swyllys 					if (temp_status != GSS_S_COMPLETE) {
327354d1447Swyllys 						*minor_status = t_minstat;
3285e01956fSGlenn Barry 						map_error(minor_status, mech);
329354d1447Swyllys 						if (output_token->length)
330354d1447Swyllys 						    (void) gss_release_buffer(
331354d1447Swyllys 								&t_minstat,
332354d1447Swyllys 								output_token);
333354d1447Swyllys 						free(d_u_cred->cred_array);
334354d1447Swyllys 						free(d_u_cred);
335354d1447Swyllys 						return (temp_status);
336354d1447Swyllys 					}
337354d1447Swyllys 				}
3387c478bd9Sstevel@tonic-gate 
339354d1447Swyllys 				if (tmp_src_name != NULL) {
340354d1447Swyllys 					status = gss_display_name(
341354d1447Swyllys 						&t_minstat,
342354d1447Swyllys 						tmp_src_name,
343354d1447Swyllys 						&d_u_cred->auxinfo.name,
344354d1447Swyllys 						&d_u_cred->auxinfo.name_type);
345354d1447Swyllys 				}
346354d1447Swyllys 
347354d1447Swyllys 				*d_cred = (gss_cred_id_t)d_u_cred;
348354d1447Swyllys 			}
349a6d402a0Swyllys 		}
350a6d402a0Swyllys 		if (ret_flags != NULL) {
351a6d402a0Swyllys 			*ret_flags = flags;
3527c478bd9Sstevel@tonic-gate 		}
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 		if (src_name == NULL && tmp_src_name != NULL)
355354d1447Swyllys 			(void) gss_release_name(&t_minstat,
3567c478bd9Sstevel@tonic-gate 					&tmp_src_name);
3577c478bd9Sstevel@tonic-gate 		return	(status);
3587c478bd9Sstevel@tonic-gate 	} else {
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 		status = GSS_S_BAD_MECH;
3617c478bd9Sstevel@tonic-gate 	}
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate error_out:
3647c478bd9Sstevel@tonic-gate 	if (union_ctx_id) {
3657c478bd9Sstevel@tonic-gate 		if (union_ctx_id->mech_type) {
3667c478bd9Sstevel@tonic-gate 			if (union_ctx_id->mech_type->elements)
3677c478bd9Sstevel@tonic-gate 				free(union_ctx_id->mech_type->elements);
3687c478bd9Sstevel@tonic-gate 			free(union_ctx_id->mech_type);
3697c478bd9Sstevel@tonic-gate 		}
3707c478bd9Sstevel@tonic-gate 		free(union_ctx_id);
3717c478bd9Sstevel@tonic-gate 		*context_handle = GSS_C_NO_CONTEXT;
3727c478bd9Sstevel@tonic-gate 	}
3737c478bd9Sstevel@tonic-gate 
374ba7b222eSGlenn Barry #if 0
375ba7b222eSGlenn Barry 	/*
376ba7b222eSGlenn Barry 	 * Solaris Kerberos
377ba7b222eSGlenn Barry 	 * Don't release, it causes a problem with error token.
378ba7b222eSGlenn Barry 	 */
3797c478bd9Sstevel@tonic-gate 	if (output_token->length)
380354d1447Swyllys 		(void) gss_release_buffer(&t_minstat, output_token);
381ba7b222eSGlenn Barry #endif
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 	if (src_name)
3847c478bd9Sstevel@tonic-gate 		*src_name = GSS_C_NO_NAME;
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 	if (tmp_src_name != GSS_C_NO_NAME)
387354d1447Swyllys 		(void) gss_release_buffer(&t_minstat,
3887c478bd9Sstevel@tonic-gate 			(gss_buffer_t)tmp_src_name);
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate 	return (status);
3917c478bd9Sstevel@tonic-gate }
3925e01956fSGlenn Barry #endif /* LEAN_CLIENT */
393