xref: /titanic_52/usr/src/uts/common/gssapi/gssd_clnt_stubs.c (revision 694c35faa87b858ecdadfe4fc592615f4eefbb07)
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
543d5cd3dSjohnlev  * Common Development and Distribution License (the "License").
643d5cd3dSjohnlev  * 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 /*
22ba7b222eSGlenn Barry  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
24b97d6ca7SMilan Jurik  * Copyright 2012 Milan Jurik. All rights reserved.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate  *  GSSAPI library stub module for gssd.
297c478bd9Sstevel@tonic-gate  */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #include <mechglueP.h>
327c478bd9Sstevel@tonic-gate #include "gssd_prot.h"
337c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #include <sys/systm.h>
367c478bd9Sstevel@tonic-gate #include <sys/types.h>
377c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
387c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
397c478bd9Sstevel@tonic-gate #include <gssapi/kgssapi_defs.h>
407c478bd9Sstevel@tonic-gate #include <sys/debug.h>
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate #ifdef GSSDEBUG
437c478bd9Sstevel@tonic-gate /*
447c478bd9Sstevel@tonic-gate  * Kernel kgssd module debugging aid. The global variable "gss_log"
457c478bd9Sstevel@tonic-gate  * is a bit mask which allows various types of debugging messages
467c478bd9Sstevel@tonic-gate  * to be printed out.
477c478bd9Sstevel@tonic-gate  *
487c478bd9Sstevel@tonic-gate  *	 gss_log & 1  will cause actual failures to be printed.
497c478bd9Sstevel@tonic-gate  *	 gss_log & 2  will cause informational messages to be
507c478bd9Sstevel@tonic-gate  *	                 printed on the client side of kgssd.
517c478bd9Sstevel@tonic-gate  *	 gss_log & 4  will cause informational messages to be
527c478bd9Sstevel@tonic-gate  *	                 printed on the server side of kgssd.
537c478bd9Sstevel@tonic-gate  *	 gss_log & 8  will cause informational messages to be
547c478bd9Sstevel@tonic-gate  *	                 printed on both client and server side of kgssd.
557c478bd9Sstevel@tonic-gate  */
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate uint_t gss_log = 1;
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate #endif /* GSSDEBUG */
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate #ifdef  DEBUG
62b97d6ca7SMilan Jurik extern void prom_printf(const char *, ...);
637c478bd9Sstevel@tonic-gate #endif
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate char *server = "localhost";
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate static OM_uint32 kgss_sign_wrapped(void *, OM_uint32 *, gss_ctx_id_t, int,
687c478bd9Sstevel@tonic-gate 	gss_buffer_t, gss_buffer_t,  OM_uint32);
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate static OM_uint32 kgss_verify_wrapped(void *, OM_uint32 *, gss_ctx_id_t,
717c478bd9Sstevel@tonic-gate 	gss_buffer_t, gss_buffer_t, int *qop_state, OM_uint32);
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate static OM_uint32 kgss_seal_wrapped(void *, OM_uint32 *, gss_ctx_id_t,
747c478bd9Sstevel@tonic-gate 	int, int, gss_buffer_t, int *, gss_buffer_t,  OM_uint32);
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate static OM_uint32 kgss_unseal_wrapped(void *, OM_uint32 *, gss_ctx_id_t,
777c478bd9Sstevel@tonic-gate 	gss_buffer_t, gss_buffer_t, int *conf_state, int *qop_state,
787c478bd9Sstevel@tonic-gate 	OM_uint32);
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate static OM_uint32 kgss_delete_sec_context_wrapped(void *, OM_uint32 *,
817c478bd9Sstevel@tonic-gate 	gssd_ctx_id_t *, gss_buffer_t, OM_uint32);
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate static void __kgss_reset_mech(gss_mechanism *, gss_OID);
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate #define	DEFAULT_MINOR_STAT	((OM_uint32) ~0)
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate OM_uint32
887c478bd9Sstevel@tonic-gate kgss_acquire_cred_wrapped(minor_status,
897c478bd9Sstevel@tonic-gate 			desired_name,
907c478bd9Sstevel@tonic-gate 			time_req,
917c478bd9Sstevel@tonic-gate 			desired_mechs,
927c478bd9Sstevel@tonic-gate 			cred_usage,
937c478bd9Sstevel@tonic-gate 			output_cred_handle,
947c478bd9Sstevel@tonic-gate 			actual_mechs,
957c478bd9Sstevel@tonic-gate 			time_rec,
967c478bd9Sstevel@tonic-gate 			uid,
977c478bd9Sstevel@tonic-gate 			gssd_cred_verifier)
987c478bd9Sstevel@tonic-gate 	OM_uint32 *minor_status;
997c478bd9Sstevel@tonic-gate 	const gss_name_t desired_name;
1007c478bd9Sstevel@tonic-gate 	OM_uint32 time_req;
1017c478bd9Sstevel@tonic-gate 	const gss_OID_set desired_mechs;
1027c478bd9Sstevel@tonic-gate 	int cred_usage;
1037c478bd9Sstevel@tonic-gate 	gssd_cred_id_t *output_cred_handle;
1047c478bd9Sstevel@tonic-gate 	gss_OID_set *actual_mechs;
1057c478bd9Sstevel@tonic-gate 	OM_uint32 *time_rec;
1067c478bd9Sstevel@tonic-gate 	uid_t uid;
1077c478bd9Sstevel@tonic-gate 	OM_uint32 *gssd_cred_verifier;
1087c478bd9Sstevel@tonic-gate {
1097c478bd9Sstevel@tonic-gate 	CLIENT *clnt;
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate 	OM_uint32 	minor_status_temp;
1127c478bd9Sstevel@tonic-gate 	gss_buffer_desc	external_name;
1137c478bd9Sstevel@tonic-gate 	gss_OID		name_type;
1147c478bd9Sstevel@tonic-gate 	enum clnt_stat	client_stat;
1157c478bd9Sstevel@tonic-gate 	int		i;
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 	gss_acquire_cred_arg arg;
1187c478bd9Sstevel@tonic-gate 	gss_acquire_cred_res res;
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate 	/* get the client handle to GSSD */
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 	if ((clnt = getgssd_handle()) == NULL) {
1237c478bd9Sstevel@tonic-gate 		GSSLOG(1, "kgss_acquire_cred: can't connect to server on %s\n",
1247c478bd9Sstevel@tonic-gate 			server);
1257c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
1267c478bd9Sstevel@tonic-gate 	}
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate 	/* convert the desired name from internal to external format */
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 	if (gss_display_name(&minor_status_temp, desired_name, &external_name,
1317c478bd9Sstevel@tonic-gate 				&name_type) != GSS_S_COMPLETE) {
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 		*minor_status = (OM_uint32) minor_status_temp;
1347c478bd9Sstevel@tonic-gate 		killgssd_handle(clnt);
1357c478bd9Sstevel@tonic-gate 		GSSLOG0(1, "kgss_acquire_cred: display name failed\n");
1367c478bd9Sstevel@tonic-gate 		return ((OM_uint32) GSS_S_FAILURE);
1377c478bd9Sstevel@tonic-gate 	}
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 	/* copy the procedure arguments into the rpc arg parameter */
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 	arg.uid = (OM_uint32) uid;
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	arg.desired_name.GSS_BUFFER_T_len = (uint_t)external_name.length;
1457c478bd9Sstevel@tonic-gate 	arg.desired_name.GSS_BUFFER_T_val = (char *)external_name.value;
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 	arg.name_type.GSS_OID_len =
1487c478bd9Sstevel@tonic-gate 		name_type == GSS_C_NULL_OID ?
1497c478bd9Sstevel@tonic-gate 			0 : (uint_t)name_type->length;
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 	arg.name_type.GSS_OID_val =
1527c478bd9Sstevel@tonic-gate 		name_type == GSS_C_NULL_OID ?
1537c478bd9Sstevel@tonic-gate 			(char *)NULL : (char *)name_type->elements;
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 	arg.time_req = time_req;
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate 	if (desired_mechs != GSS_C_NULL_OID_SET) {
1587c478bd9Sstevel@tonic-gate 		arg.desired_mechs.GSS_OID_SET_len =
1597c478bd9Sstevel@tonic-gate 			(uint_t)desired_mechs->count;
1607c478bd9Sstevel@tonic-gate 		arg.desired_mechs.GSS_OID_SET_val = (GSS_OID *)
1617c478bd9Sstevel@tonic-gate 			MALLOC(sizeof (GSS_OID) * desired_mechs->count);
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate 		for (i = 0; i < desired_mechs->count; i++) {
1647c478bd9Sstevel@tonic-gate 		    arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_len =
1657c478bd9Sstevel@tonic-gate 			(uint_t)desired_mechs->elements[i].length;
1667c478bd9Sstevel@tonic-gate 		    arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val =
1677c478bd9Sstevel@tonic-gate 			(char *)MALLOC(desired_mechs->elements[i].length);
1687c478bd9Sstevel@tonic-gate 		    (void) memcpy(
1697c478bd9Sstevel@tonic-gate 			arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val,
1707c478bd9Sstevel@tonic-gate 			desired_mechs->elements[i].elements,
1717c478bd9Sstevel@tonic-gate 			desired_mechs->elements[i].length);
1727c478bd9Sstevel@tonic-gate 		}
1737c478bd9Sstevel@tonic-gate 	} else
1747c478bd9Sstevel@tonic-gate 		arg.desired_mechs.GSS_OID_SET_len = 0;
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	arg.cred_usage = cred_usage;
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 	/* call the remote procedure */
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 	bzero((caddr_t)&res, sizeof (res));
1817c478bd9Sstevel@tonic-gate 	client_stat = gss_acquire_cred_1(&arg, &res, clnt);
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate 	(void) gss_release_buffer(&minor_status_temp, &external_name);
1847c478bd9Sstevel@tonic-gate 	if (desired_mechs != GSS_C_NULL_OID_SET) {
1857c478bd9Sstevel@tonic-gate 		for (i = 0; i < desired_mechs->count; i++)
1867c478bd9Sstevel@tonic-gate 			FREE(arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val,
1877c478bd9Sstevel@tonic-gate 			    arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_len);
1887c478bd9Sstevel@tonic-gate 		FREE(arg.desired_mechs.GSS_OID_SET_val,
1897c478bd9Sstevel@tonic-gate 		    arg.desired_mechs.GSS_OID_SET_len * sizeof (GSS_OID));
1907c478bd9Sstevel@tonic-gate 	}
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 	if (client_stat != RPC_SUCCESS) {
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 		/*
1957c478bd9Sstevel@tonic-gate 		 * if the RPC call times out, null out all return arguments,
1967c478bd9Sstevel@tonic-gate 		 * set minor_status to its maximum value, and return
1977c478bd9Sstevel@tonic-gate 		 * GSS_S_FAILURE
1987c478bd9Sstevel@tonic-gate 		 */
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 		if (minor_status != NULL)
2017c478bd9Sstevel@tonic-gate 			*minor_status = DEFAULT_MINOR_STAT;
2027c478bd9Sstevel@tonic-gate 		if (output_cred_handle != NULL)
2037c478bd9Sstevel@tonic-gate 			*output_cred_handle = NULL;
2047c478bd9Sstevel@tonic-gate 		if (actual_mechs != NULL)
2057c478bd9Sstevel@tonic-gate 			*actual_mechs = NULL;
2067c478bd9Sstevel@tonic-gate 		if (time_rec != NULL)
2077c478bd9Sstevel@tonic-gate 			*time_rec = 0;
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 		killgssd_handle(clnt);
2107c478bd9Sstevel@tonic-gate 		GSSLOG0(1, "kgss_acquire_cred: RPC call times out\n");
2117c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
2127c478bd9Sstevel@tonic-gate 	}
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 	/* copy the rpc results into the return arguments */
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate 	if (minor_status != NULL)
2177c478bd9Sstevel@tonic-gate 		*minor_status = res.minor_status;
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 	if (output_cred_handle != NULL &&
2207c478bd9Sstevel@tonic-gate 		(res.status == GSS_S_COMPLETE)) {
2217c478bd9Sstevel@tonic-gate 	    *output_cred_handle =
2227c478bd9Sstevel@tonic-gate 		*((gssd_cred_id_t *)res.output_cred_handle.GSS_CRED_ID_T_val);
2237c478bd9Sstevel@tonic-gate 	    *gssd_cred_verifier = res.gssd_cred_verifier;
2247c478bd9Sstevel@tonic-gate 	}
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 	if (res.status == GSS_S_COMPLETE &&
2277c478bd9Sstevel@tonic-gate 		res.actual_mechs.GSS_OID_SET_len != 0 &&
2287c478bd9Sstevel@tonic-gate 		actual_mechs != NULL) {
2297c478bd9Sstevel@tonic-gate 		*actual_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
2307c478bd9Sstevel@tonic-gate 		(*actual_mechs)->count =
2317c478bd9Sstevel@tonic-gate 					(int)res.actual_mechs.GSS_OID_SET_len;
2327c478bd9Sstevel@tonic-gate 		(*actual_mechs)->elements = (gss_OID)
2337c478bd9Sstevel@tonic-gate 			MALLOC(sizeof (gss_OID_desc) * (*actual_mechs)->count);
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 		for (i = 0; i < (*actual_mechs)->count; i++) {
2367c478bd9Sstevel@tonic-gate 		    (*actual_mechs)->elements[i].length = (OM_uint32)
2377c478bd9Sstevel@tonic-gate 			res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_len;
2387c478bd9Sstevel@tonic-gate 		    (*actual_mechs)->elements[i].elements =
2397c478bd9Sstevel@tonic-gate 			(void *) MALLOC((*actual_mechs)->elements[i].length);
2407c478bd9Sstevel@tonic-gate 		    (void) memcpy((*actual_mechs)->elements[i].elements,
2417c478bd9Sstevel@tonic-gate 			res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_val,
2427c478bd9Sstevel@tonic-gate 			(*actual_mechs)->elements[i].length);
2437c478bd9Sstevel@tonic-gate 		}
2447c478bd9Sstevel@tonic-gate 	} else {
2457c478bd9Sstevel@tonic-gate 		if (res.status == GSS_S_COMPLETE &&
2467c478bd9Sstevel@tonic-gate 			actual_mechs != NULL)
2477c478bd9Sstevel@tonic-gate 			(*actual_mechs) = NULL;
2487c478bd9Sstevel@tonic-gate 	}
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 	if (time_rec != NULL)
2517c478bd9Sstevel@tonic-gate 		*time_rec = res.time_rec;
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 	/*
2547c478bd9Sstevel@tonic-gate 	 * free the memory allocated for the results and return with the status
2557c478bd9Sstevel@tonic-gate 	 * received in the rpc call
2567c478bd9Sstevel@tonic-gate 	 */
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 	clnt_freeres(clnt, xdr_gss_acquire_cred_res, (caddr_t)&res);
2597c478bd9Sstevel@tonic-gate 	killgssd_handle(clnt);
2607c478bd9Sstevel@tonic-gate 	return (res.status);
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate }
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate OM_uint32
2657c478bd9Sstevel@tonic-gate kgss_acquire_cred(minor_status,
2667c478bd9Sstevel@tonic-gate 		desired_name,
2677c478bd9Sstevel@tonic-gate 		time_req,
2687c478bd9Sstevel@tonic-gate 		desired_mechs,
2697c478bd9Sstevel@tonic-gate 		cred_usage,
2707c478bd9Sstevel@tonic-gate 		output_cred_handle,
2717c478bd9Sstevel@tonic-gate 		actual_mechs,
2727c478bd9Sstevel@tonic-gate 		time_rec,
2737c478bd9Sstevel@tonic-gate 		uid)
2747c478bd9Sstevel@tonic-gate 	OM_uint32 *minor_status;
2757c478bd9Sstevel@tonic-gate 	const gss_name_t desired_name;
2767c478bd9Sstevel@tonic-gate 	OM_uint32 time_req;
2777c478bd9Sstevel@tonic-gate 	const gss_OID_set desired_mechs;
2787c478bd9Sstevel@tonic-gate 	int cred_usage;
2797c478bd9Sstevel@tonic-gate 	gss_cred_id_t *output_cred_handle;
2807c478bd9Sstevel@tonic-gate 	gss_OID_set *actual_mechs;
2817c478bd9Sstevel@tonic-gate 	OM_uint32 *time_rec;
2827c478bd9Sstevel@tonic-gate 	uid_t uid;
2837c478bd9Sstevel@tonic-gate {
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 	OM_uint32	err;
2867c478bd9Sstevel@tonic-gate 	struct kgss_cred *kcred;
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 	kcred = KGSS_CRED_ALLOC();
2897c478bd9Sstevel@tonic-gate 	*output_cred_handle = (gss_cred_id_t)kcred;
2907c478bd9Sstevel@tonic-gate 	err = kgss_acquire_cred_wrapped(minor_status, desired_name, time_req,
2917c478bd9Sstevel@tonic-gate 		desired_mechs, cred_usage, &kcred->gssd_cred, actual_mechs,
2927c478bd9Sstevel@tonic-gate 		time_rec, uid, &kcred->gssd_cred_verifier);
2937c478bd9Sstevel@tonic-gate 	if (GSS_ERROR(err)) {
2947c478bd9Sstevel@tonic-gate 		KGSS_CRED_FREE(kcred);
2957c478bd9Sstevel@tonic-gate 		*output_cred_handle = GSS_C_NO_CREDENTIAL;
2967c478bd9Sstevel@tonic-gate 	}
2977c478bd9Sstevel@tonic-gate 	return (err);
2987c478bd9Sstevel@tonic-gate }
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate OM_uint32
3017c478bd9Sstevel@tonic-gate kgss_add_cred_wrapped(minor_status,
3027c478bd9Sstevel@tonic-gate 			input_cred_handle,
3037c478bd9Sstevel@tonic-gate 			gssd_cred_verifier,
3047c478bd9Sstevel@tonic-gate 			desired_name,
3057c478bd9Sstevel@tonic-gate 			desired_mech_type,
3067c478bd9Sstevel@tonic-gate 			cred_usage,
3077c478bd9Sstevel@tonic-gate 			initiator_time_req,
3087c478bd9Sstevel@tonic-gate 			acceptor_time_req,
3097c478bd9Sstevel@tonic-gate 			actual_mechs,
3107c478bd9Sstevel@tonic-gate 			initiator_time_rec,
3117c478bd9Sstevel@tonic-gate 			acceptor_time_rec,
3127c478bd9Sstevel@tonic-gate 			uid)
3137c478bd9Sstevel@tonic-gate 	OM_uint32 *minor_status;
3147c478bd9Sstevel@tonic-gate 	gssd_cred_id_t input_cred_handle;
3157c478bd9Sstevel@tonic-gate 	OM_uint32 gssd_cred_verifier;
3167c478bd9Sstevel@tonic-gate 	gss_name_t desired_name;
3177c478bd9Sstevel@tonic-gate 	gss_OID desired_mech_type;
3187c478bd9Sstevel@tonic-gate 	int cred_usage;
3197c478bd9Sstevel@tonic-gate 	int initiator_time_req;
3207c478bd9Sstevel@tonic-gate 	int acceptor_time_req;
3217c478bd9Sstevel@tonic-gate 	gss_OID_set *actual_mechs;
3227c478bd9Sstevel@tonic-gate 	OM_uint32 *initiator_time_rec;
3237c478bd9Sstevel@tonic-gate 	OM_uint32 *acceptor_time_rec;
3247c478bd9Sstevel@tonic-gate 	uid_t uid;
3257c478bd9Sstevel@tonic-gate {
3267c478bd9Sstevel@tonic-gate 	CLIENT *clnt;
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate 	OM_uint32 	minor_status_temp;
3297c478bd9Sstevel@tonic-gate 	gss_buffer_desc	external_name;
3307c478bd9Sstevel@tonic-gate 	gss_OID		name_type;
3317c478bd9Sstevel@tonic-gate 	int		i;
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 	gss_add_cred_arg arg;
3347c478bd9Sstevel@tonic-gate 	gss_add_cred_res res;
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 	/*
3387c478bd9Sstevel@tonic-gate 	 * NULL the params here once
3397c478bd9Sstevel@tonic-gate 	 * If there are errors then we won't
3407c478bd9Sstevel@tonic-gate 	 * have to do it for every error
3417c478bd9Sstevel@tonic-gate 	 * case
3427c478bd9Sstevel@tonic-gate 	 */
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 	if (minor_status != NULL)
3457c478bd9Sstevel@tonic-gate 		*minor_status = DEFAULT_MINOR_STAT;
3467c478bd9Sstevel@tonic-gate 	if (actual_mechs != NULL)
3477c478bd9Sstevel@tonic-gate 		*actual_mechs = NULL;
3487c478bd9Sstevel@tonic-gate 	if (initiator_time_rec != NULL)
3497c478bd9Sstevel@tonic-gate 		*initiator_time_rec = 0;
3507c478bd9Sstevel@tonic-gate 	if (acceptor_time_rec != NULL)
3517c478bd9Sstevel@tonic-gate 			*acceptor_time_rec = 0;
3527c478bd9Sstevel@tonic-gate 	/* get the client handle to GSSD */
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 	if ((clnt = getgssd_handle()) == NULL) {
3557c478bd9Sstevel@tonic-gate 		GSSLOG(1, "kgss_add_cred: can't connect to server on %s\n",
3567c478bd9Sstevel@tonic-gate 			server);
3577c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
3587c478bd9Sstevel@tonic-gate 	}
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 	/* convert the desired name from internal to external format */
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate 	if (gss_display_name(&minor_status_temp, desired_name, &external_name,
3647c478bd9Sstevel@tonic-gate 				&name_type) != GSS_S_COMPLETE) {
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 		*minor_status = (OM_uint32) minor_status_temp;
3677c478bd9Sstevel@tonic-gate 		killgssd_handle(clnt);
3687c478bd9Sstevel@tonic-gate 		GSSLOG0(1, "kgss_acquire_cred: display name failed\n");
3697c478bd9Sstevel@tonic-gate 		return ((OM_uint32) GSS_S_FAILURE);
3707c478bd9Sstevel@tonic-gate 	}
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate 	/* copy the procedure arguments into the rpc arg parameter */
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate 	arg.uid = (OM_uint32)uid;
3767c478bd9Sstevel@tonic-gate 	arg.input_cred_handle.GSS_CRED_ID_T_len =
377*d4f95bf4SRichard Lowe 			input_cred_handle == GSSD_NO_CREDENTIAL ?
3787c478bd9Sstevel@tonic-gate 			0 : (uint_t)sizeof (gssd_cred_id_t);
3797c478bd9Sstevel@tonic-gate 	arg.input_cred_handle.GSS_CRED_ID_T_val = (char *)&input_cred_handle;
3807c478bd9Sstevel@tonic-gate 	arg.gssd_cred_verifier = gssd_cred_verifier;
3817c478bd9Sstevel@tonic-gate 	arg.desired_name.GSS_BUFFER_T_len = (uint_t)external_name.length;
3827c478bd9Sstevel@tonic-gate 	arg.desired_name.GSS_BUFFER_T_val = (char *)external_name.value;
3837c478bd9Sstevel@tonic-gate 	arg.name_type.GSS_OID_len =
3847c478bd9Sstevel@tonic-gate 		name_type == GSS_C_NULL_OID ?
3857c478bd9Sstevel@tonic-gate 			0 : (uint_t)name_type->length;
3867c478bd9Sstevel@tonic-gate 	arg.name_type.GSS_OID_val =
3877c478bd9Sstevel@tonic-gate 		name_type == GSS_C_NULL_OID ?
3887c478bd9Sstevel@tonic-gate 			(char *)NULL : (char *)name_type->elements;
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate 	arg.desired_mech_type.GSS_OID_len =
3917c478bd9Sstevel@tonic-gate 		(uint_t)(desired_mech_type != GSS_C_NULL_OID ?
3927c478bd9Sstevel@tonic-gate 		desired_mech_type->length : 0);
3937c478bd9Sstevel@tonic-gate 	arg.desired_mech_type.GSS_OID_val =
3947c478bd9Sstevel@tonic-gate 		(char *)(desired_mech_type != GSS_C_NULL_OID ?
3957c478bd9Sstevel@tonic-gate 		desired_mech_type->elements : 0);
3967c478bd9Sstevel@tonic-gate 	arg.cred_usage = cred_usage;
3977c478bd9Sstevel@tonic-gate 	arg.initiator_time_req = initiator_time_req;
3987c478bd9Sstevel@tonic-gate 	arg.acceptor_time_req = acceptor_time_req;
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 	/* call the remote procedure */
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 	bzero((caddr_t)&res, sizeof (res));
4037c478bd9Sstevel@tonic-gate 	if (gss_add_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 		/*
4067c478bd9Sstevel@tonic-gate 		 * if the RPC call times out, null out all return arguments,
4077c478bd9Sstevel@tonic-gate 		 * set minor_status to its maximum value, and return
4087c478bd9Sstevel@tonic-gate 		 * GSS_S_FAILURE
4097c478bd9Sstevel@tonic-gate 		 */
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 		killgssd_handle(clnt);
4127c478bd9Sstevel@tonic-gate 		(void) gss_release_buffer(&minor_status_temp, &external_name);
4137c478bd9Sstevel@tonic-gate 		GSSLOG0(1, "kgss_add_cred: RPC call times out\n");
4147c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
4157c478bd9Sstevel@tonic-gate 	}
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate 	/* free the allocated memory for the flattened name */
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate 	(void) gss_release_buffer(&minor_status_temp, &external_name);
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 	/* copy the rpc results into the return arguments */
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate 	if (minor_status != NULL)
4247c478bd9Sstevel@tonic-gate 		*minor_status = res.minor_status;
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate 	if (res.status == GSS_S_COMPLETE &&
4277c478bd9Sstevel@tonic-gate 		res.actual_mechs.GSS_OID_SET_len != 0 &&
4287c478bd9Sstevel@tonic-gate 		actual_mechs != NULL) {
4297c478bd9Sstevel@tonic-gate 		*actual_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
4307c478bd9Sstevel@tonic-gate 		(*actual_mechs)->count =
4317c478bd9Sstevel@tonic-gate 					(int)res.actual_mechs.GSS_OID_SET_len;
4327c478bd9Sstevel@tonic-gate 		(*actual_mechs)->elements = (gss_OID)
4337c478bd9Sstevel@tonic-gate 			MALLOC(sizeof (gss_OID_desc) * (*actual_mechs)->count);
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 		for (i = 0; i < (*actual_mechs)->count; i++) {
4367c478bd9Sstevel@tonic-gate 		    (*actual_mechs)->elements[i].length = (OM_uint32)
4377c478bd9Sstevel@tonic-gate 			res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_len;
4387c478bd9Sstevel@tonic-gate 		    (*actual_mechs)->elements[i].elements =
4397c478bd9Sstevel@tonic-gate 			(void *) MALLOC((*actual_mechs)->elements[i].length);
4407c478bd9Sstevel@tonic-gate 		    (void) memcpy((*actual_mechs)->elements[i].elements,
4417c478bd9Sstevel@tonic-gate 			res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_val,
4427c478bd9Sstevel@tonic-gate 			(*actual_mechs)->elements[i].length);
4437c478bd9Sstevel@tonic-gate 		}
4447c478bd9Sstevel@tonic-gate 	} else {
4457c478bd9Sstevel@tonic-gate 		if (res.status == GSS_S_COMPLETE && actual_mechs != NULL)
4467c478bd9Sstevel@tonic-gate 			(*actual_mechs) = NULL;
4477c478bd9Sstevel@tonic-gate 	}
4487c478bd9Sstevel@tonic-gate 	if (initiator_time_rec != NULL)
4497c478bd9Sstevel@tonic-gate 		*initiator_time_rec = res.acceptor_time_rec;
4507c478bd9Sstevel@tonic-gate 	if (acceptor_time_rec != NULL)
4517c478bd9Sstevel@tonic-gate 		*acceptor_time_rec = res.acceptor_time_rec;
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate 	/*
4547c478bd9Sstevel@tonic-gate 	 * free the memory allocated for the results and return with the status
4557c478bd9Sstevel@tonic-gate 	 * received in the rpc call
4567c478bd9Sstevel@tonic-gate 	 */
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 	clnt_freeres(clnt, xdr_gss_add_cred_res, (caddr_t)&res);
4597c478bd9Sstevel@tonic-gate 	killgssd_handle(clnt);
4607c478bd9Sstevel@tonic-gate 	return (res.status);
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate }
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate OM_uint32
4657c478bd9Sstevel@tonic-gate kgss_add_cred(minor_status,
4667c478bd9Sstevel@tonic-gate 			input_cred_handle,
4677c478bd9Sstevel@tonic-gate 			desired_name,
4687c478bd9Sstevel@tonic-gate 			desired_mech_type,
4697c478bd9Sstevel@tonic-gate 			cred_usage,
4707c478bd9Sstevel@tonic-gate 			initiator_time_req,
4717c478bd9Sstevel@tonic-gate 			acceptor_time_req,
4727c478bd9Sstevel@tonic-gate 			actual_mechs,
4737c478bd9Sstevel@tonic-gate 			initiator_time_rec,
4747c478bd9Sstevel@tonic-gate 			acceptor_time_rec,
4757c478bd9Sstevel@tonic-gate 			uid)
4767c478bd9Sstevel@tonic-gate 	OM_uint32 *minor_status;
4777c478bd9Sstevel@tonic-gate 	gss_cred_id_t input_cred_handle;
4787c478bd9Sstevel@tonic-gate 	gss_name_t desired_name;
4797c478bd9Sstevel@tonic-gate 	gss_OID desired_mech_type;
4807c478bd9Sstevel@tonic-gate 	int cred_usage;
4817c478bd9Sstevel@tonic-gate 	int initiator_time_req;
4827c478bd9Sstevel@tonic-gate 	int acceptor_time_req;
4837c478bd9Sstevel@tonic-gate 	gss_OID_set *actual_mechs;
4847c478bd9Sstevel@tonic-gate 	OM_uint32 *initiator_time_rec;
4857c478bd9Sstevel@tonic-gate 	OM_uint32 *acceptor_time_rec;
4867c478bd9Sstevel@tonic-gate 	uid_t uid;
4877c478bd9Sstevel@tonic-gate {
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate 	OM_uint32	err;
4907c478bd9Sstevel@tonic-gate 	OM_uint32 gssd_cred_verifier;
4917c478bd9Sstevel@tonic-gate 	gssd_cred_id_t gssd_input_cred_handle;
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate 	if (input_cred_handle != GSS_C_NO_CREDENTIAL) {
4947c478bd9Sstevel@tonic-gate 		gssd_cred_verifier = KCRED_TO_CREDV(input_cred_handle);
4957c478bd9Sstevel@tonic-gate 		gssd_input_cred_handle = KCRED_TO_CRED(input_cred_handle);
496*d4f95bf4SRichard Lowe 	} else {
497*d4f95bf4SRichard Lowe 		gssd_input_cred_handle = GSSD_NO_CREDENTIAL;
498*d4f95bf4SRichard Lowe 	}
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate 	err = kgss_add_cred_wrapped(minor_status, gssd_input_cred_handle,
5017c478bd9Sstevel@tonic-gate 			gssd_cred_verifier, desired_name, desired_mech_type,
5027c478bd9Sstevel@tonic-gate 			cred_usage, initiator_time_req, acceptor_time_req,
5037c478bd9Sstevel@tonic-gate 			actual_mechs, initiator_time_rec,
5047c478bd9Sstevel@tonic-gate 			acceptor_time_rec, uid);
5057c478bd9Sstevel@tonic-gate 	return (err);
5067c478bd9Sstevel@tonic-gate }
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate 
5097c478bd9Sstevel@tonic-gate OM_uint32
5107c478bd9Sstevel@tonic-gate kgss_release_cred_wrapped(minor_status,
5117c478bd9Sstevel@tonic-gate 			cred_handle,
5127c478bd9Sstevel@tonic-gate 			uid,
5137c478bd9Sstevel@tonic-gate 			gssd_cred_verifier)
5147c478bd9Sstevel@tonic-gate     OM_uint32 *minor_status;
5157c478bd9Sstevel@tonic-gate     gssd_cred_id_t *cred_handle;
5167c478bd9Sstevel@tonic-gate     uid_t uid;
5177c478bd9Sstevel@tonic-gate     OM_uint32  gssd_cred_verifier;
5187c478bd9Sstevel@tonic-gate {
5197c478bd9Sstevel@tonic-gate 	CLIENT *clnt;
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 	gss_release_cred_arg arg;
5227c478bd9Sstevel@tonic-gate 	gss_release_cred_res res;
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 	/* get the client handle to GSSD */
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate 	if ((clnt = getgssd_handle()) == NULL) {
5287c478bd9Sstevel@tonic-gate 		GSSLOG(1, "kgss_release_cred: can't connect to server on %s\n",
5297c478bd9Sstevel@tonic-gate 			server);
5307c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
5317c478bd9Sstevel@tonic-gate 	}
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 	/* copy the procedure arguments into the rpc arg parameter */
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate 	arg.uid = (OM_uint32)uid;
5367c478bd9Sstevel@tonic-gate 	arg.gssd_cred_verifier = gssd_cred_verifier;
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate 	if (cred_handle != NULL) {
5397c478bd9Sstevel@tonic-gate 		arg.cred_handle.GSS_CRED_ID_T_len =
5407c478bd9Sstevel@tonic-gate 					(uint_t)sizeof (gssd_cred_id_t);
5417c478bd9Sstevel@tonic-gate 		arg.cred_handle.GSS_CRED_ID_T_val = (char *)cred_handle;
5427c478bd9Sstevel@tonic-gate 	} else
5437c478bd9Sstevel@tonic-gate 		arg.cred_handle.GSS_CRED_ID_T_len = 0;
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 	/* call the remote procedure */
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate 	bzero((caddr_t)&res, sizeof (res));
5487c478bd9Sstevel@tonic-gate 	if (gss_release_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 	/*
5517c478bd9Sstevel@tonic-gate 	 * if the RPC call times out, null out all return arguments, set
5527c478bd9Sstevel@tonic-gate 	 * minor_status to its maximum value, and return GSS_S_FAILURE
5537c478bd9Sstevel@tonic-gate 	 */
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate 		if (minor_status != NULL)
5567c478bd9Sstevel@tonic-gate 			*minor_status = DEFAULT_MINOR_STAT;
5577c478bd9Sstevel@tonic-gate 		if (cred_handle != NULL)
5587c478bd9Sstevel@tonic-gate 			*cred_handle = NULL;
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 		killgssd_handle(clnt);
5617c478bd9Sstevel@tonic-gate 		GSSLOG0(1, "kgss_release_cred: RPC call times out\n");
5627c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
5637c478bd9Sstevel@tonic-gate 	}
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate 	/* if the release succeeded, null out the cred_handle */
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate 	if (res.status == GSS_S_COMPLETE && cred_handle != NULL)
5687c478bd9Sstevel@tonic-gate 		*cred_handle = NULL;
5697c478bd9Sstevel@tonic-gate 
5707c478bd9Sstevel@tonic-gate 	/* copy the rpc results into the return arguments */
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate 	if (minor_status != NULL)
5737c478bd9Sstevel@tonic-gate 		*minor_status = res.minor_status;
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate 	/* return with status returned in rpc call */
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate 	killgssd_handle(clnt);
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate 	return (res.status);
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate }
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate OM_uint32
5847c478bd9Sstevel@tonic-gate kgss_release_cred(minor_status,
5857c478bd9Sstevel@tonic-gate 			cred_handle,
5867c478bd9Sstevel@tonic-gate 			uid)
5877c478bd9Sstevel@tonic-gate     OM_uint32 *minor_status;
5887c478bd9Sstevel@tonic-gate     gss_cred_id_t *cred_handle;
5897c478bd9Sstevel@tonic-gate     uid_t uid;
5907c478bd9Sstevel@tonic-gate 
5917c478bd9Sstevel@tonic-gate {
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	OM_uint32	err;
5947c478bd9Sstevel@tonic-gate 	struct kgss_cred *kcred;
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 	if (*cred_handle == GSS_C_NO_CREDENTIAL)
5977c478bd9Sstevel@tonic-gate 		return (GSS_S_COMPLETE);
5987c478bd9Sstevel@tonic-gate 	else
5997c478bd9Sstevel@tonic-gate 		kcred = KCRED_TO_KGSS_CRED(*cred_handle);
6007c478bd9Sstevel@tonic-gate 
6017c478bd9Sstevel@tonic-gate 	err = kgss_release_cred_wrapped(minor_status, &kcred->gssd_cred,
6027c478bd9Sstevel@tonic-gate 		uid, kcred->gssd_cred_verifier);
6037c478bd9Sstevel@tonic-gate 	KGSS_CRED_FREE(kcred);
6047c478bd9Sstevel@tonic-gate 	*cred_handle = GSS_C_NO_CREDENTIAL;
6057c478bd9Sstevel@tonic-gate 	return (err);
6067c478bd9Sstevel@tonic-gate }
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate static OM_uint32
6097c478bd9Sstevel@tonic-gate kgss_init_sec_context_wrapped(
6107c478bd9Sstevel@tonic-gate 	OM_uint32 *minor_status,
6117c478bd9Sstevel@tonic-gate 	const gssd_cred_id_t claimant_cred_handle,
6127c478bd9Sstevel@tonic-gate 	OM_uint32 gssd_cred_verifier,
6137c478bd9Sstevel@tonic-gate 	gssd_ctx_id_t *context_handle,
6147c478bd9Sstevel@tonic-gate 	OM_uint32 *gssd_context_verifier,
6157c478bd9Sstevel@tonic-gate 	const gss_name_t target_name,
6167c478bd9Sstevel@tonic-gate 	const gss_OID mech_type,
6177c478bd9Sstevel@tonic-gate 	int req_flags,
6187c478bd9Sstevel@tonic-gate 	OM_uint32 time_req,
6197c478bd9Sstevel@tonic-gate 	const gss_channel_bindings_t input_chan_bindings,
6207c478bd9Sstevel@tonic-gate 	const gss_buffer_t input_token,
6217c478bd9Sstevel@tonic-gate 	gss_OID *actual_mech_type,
6227c478bd9Sstevel@tonic-gate 	gss_buffer_t output_token,
6237c478bd9Sstevel@tonic-gate 	int *ret_flags,
6247c478bd9Sstevel@tonic-gate 	OM_uint32 *time_rec,
6257c478bd9Sstevel@tonic-gate 	uid_t uid)
6267c478bd9Sstevel@tonic-gate {
6277c478bd9Sstevel@tonic-gate 	CLIENT *clnt;
6287c478bd9Sstevel@tonic-gate 
6297c478bd9Sstevel@tonic-gate 	OM_uint32 	minor_status_temp;
6307c478bd9Sstevel@tonic-gate 	gss_buffer_desc	external_name;
6317c478bd9Sstevel@tonic-gate 	gss_OID		name_type;
6327c478bd9Sstevel@tonic-gate 
6337c478bd9Sstevel@tonic-gate 	gss_init_sec_context_arg arg;
6347c478bd9Sstevel@tonic-gate 	gss_init_sec_context_res res;
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate 	/* get the client handle to GSSD */
6377c478bd9Sstevel@tonic-gate 
6387c478bd9Sstevel@tonic-gate 	if ((clnt = getgssd_handle()) == NULL) {
6397c478bd9Sstevel@tonic-gate 		GSSLOG(1,
6407c478bd9Sstevel@tonic-gate 		    "kgss_init_sec_context: can't connect to server on %s\n",
6417c478bd9Sstevel@tonic-gate 		    server);
6427c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
6437c478bd9Sstevel@tonic-gate 	}
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate 	/* convert the target name from internal to external format */
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 	if (gss_display_name(&minor_status_temp, target_name,
6487c478bd9Sstevel@tonic-gate 	    &external_name, &name_type) != GSS_S_COMPLETE) {
6497c478bd9Sstevel@tonic-gate 
6507c478bd9Sstevel@tonic-gate 		*minor_status = (OM_uint32) minor_status_temp;
6517c478bd9Sstevel@tonic-gate 		killgssd_handle(clnt);
6527c478bd9Sstevel@tonic-gate 		GSSLOG0(1, "kgss_init_sec_context: can't display name\n");
6537c478bd9Sstevel@tonic-gate 		return ((OM_uint32) GSS_S_FAILURE);
6547c478bd9Sstevel@tonic-gate 	}
6557c478bd9Sstevel@tonic-gate 
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate 	/* copy the procedure arguments into the rpc arg parameter */
6587c478bd9Sstevel@tonic-gate 
6597c478bd9Sstevel@tonic-gate 	arg.uid = (OM_uint32)uid;
6607c478bd9Sstevel@tonic-gate 
6617c478bd9Sstevel@tonic-gate 	arg.context_handle.GSS_CTX_ID_T_len =
662*d4f95bf4SRichard Lowe 	    *context_handle == GSSD_NO_CONTEXT ?
6637c478bd9Sstevel@tonic-gate 	    0 : (uint_t)sizeof (gssd_ctx_id_t);
6647c478bd9Sstevel@tonic-gate 	arg.context_handle.GSS_CTX_ID_T_val =  (char *)context_handle;
6657c478bd9Sstevel@tonic-gate 
6667c478bd9Sstevel@tonic-gate 	arg.gssd_context_verifier =  *gssd_context_verifier;
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate 	arg.claimant_cred_handle.GSS_CRED_ID_T_len =
669*d4f95bf4SRichard Lowe 	    claimant_cred_handle == GSSD_NO_CREDENTIAL ?
6707c478bd9Sstevel@tonic-gate 	    0 : (uint_t)sizeof (gssd_cred_id_t);
6717c478bd9Sstevel@tonic-gate 	arg.claimant_cred_handle.GSS_CRED_ID_T_val =
6727c478bd9Sstevel@tonic-gate 	    (char *)&claimant_cred_handle;
6737c478bd9Sstevel@tonic-gate 	arg.gssd_cred_verifier = gssd_cred_verifier;
6747c478bd9Sstevel@tonic-gate 
6757c478bd9Sstevel@tonic-gate 	arg.target_name.GSS_BUFFER_T_len = (uint_t)external_name.length;
6767c478bd9Sstevel@tonic-gate 	arg.target_name.GSS_BUFFER_T_val = (char *)external_name.value;
6777c478bd9Sstevel@tonic-gate 
6787c478bd9Sstevel@tonic-gate 	arg.name_type.GSS_OID_len =
679*d4f95bf4SRichard Lowe 	    name_type == GSS_C_NULL_OID ? 0 : (uint_t)name_type->length;
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate 	arg.name_type.GSS_OID_val =
6827c478bd9Sstevel@tonic-gate 	    name_type == GSS_C_NULL_OID ?
6837c478bd9Sstevel@tonic-gate 	    (char *)NULL : (char *)name_type->elements;
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate 	arg.mech_type.GSS_OID_len = (uint_t)(mech_type != GSS_C_NULL_OID ?
6867c478bd9Sstevel@tonic-gate 	    mech_type->length : 0);
6877c478bd9Sstevel@tonic-gate 	arg.mech_type.GSS_OID_val = (char *)(mech_type != GSS_C_NULL_OID ?
6887c478bd9Sstevel@tonic-gate 	    mech_type->elements : 0);
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate 	arg.req_flags = req_flags;
6917c478bd9Sstevel@tonic-gate 
6927c478bd9Sstevel@tonic-gate 	arg.time_req = time_req;
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate 	if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) {
6957c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.present = YES;
6967c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.initiator_addrtype =
6977c478bd9Sstevel@tonic-gate 		    input_chan_bindings->initiator_addrtype;
6987c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len =
6997c478bd9Sstevel@tonic-gate 		    (uint_t)input_chan_bindings->initiator_address.length;
7007c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val =
7017c478bd9Sstevel@tonic-gate 		    (void *)input_chan_bindings->initiator_address.value;
7027c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.acceptor_addrtype =
7037c478bd9Sstevel@tonic-gate 		    input_chan_bindings->acceptor_addrtype;
7047c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len =
7057c478bd9Sstevel@tonic-gate 		    (uint_t)input_chan_bindings->acceptor_address.length;
7067c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val =
7077c478bd9Sstevel@tonic-gate 		    (void *)input_chan_bindings->acceptor_address.value;
7087c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.application_data.GSS_BUFFER_T_len =
7097c478bd9Sstevel@tonic-gate 		    (uint_t)input_chan_bindings->application_data.length;
7107c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.application_data.GSS_BUFFER_T_val =
7117c478bd9Sstevel@tonic-gate 		    (void *)input_chan_bindings->application_data.value;
7127c478bd9Sstevel@tonic-gate 	} else {
7137c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.present = NO;
7147c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.initiator_addrtype = 0;
7157c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = 0;
7167c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = 0;
7177c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.acceptor_addrtype = 0;
7187c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = 0;
7197c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = 0;
7207c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = 0;
7217c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = 0;
7227c478bd9Sstevel@tonic-gate 	}
7237c478bd9Sstevel@tonic-gate 
7247c478bd9Sstevel@tonic-gate 	arg.input_token.GSS_BUFFER_T_len =
725b97d6ca7SMilan Jurik 	    (uint_t)(input_token != GSS_C_NO_BUFFER ? input_token->length : 0);
7267c478bd9Sstevel@tonic-gate 	arg.input_token.GSS_BUFFER_T_val =
727b97d6ca7SMilan Jurik 	    (char *)(input_token != GSS_C_NO_BUFFER ? input_token->value : 0);
7287c478bd9Sstevel@tonic-gate 
7297c478bd9Sstevel@tonic-gate 	/* call the remote procedure */
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate 	bzero((caddr_t)&res, sizeof (res));
7327c478bd9Sstevel@tonic-gate 	if (gss_init_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
7337c478bd9Sstevel@tonic-gate 
7347c478bd9Sstevel@tonic-gate 	/*
7357c478bd9Sstevel@tonic-gate 	 * if the RPC call times out, null out all return arguments, set
7367c478bd9Sstevel@tonic-gate 	 * minor_status to its maximum value, and return GSS_S_FAILURE
7377c478bd9Sstevel@tonic-gate 	 */
7387c478bd9Sstevel@tonic-gate 
7397c478bd9Sstevel@tonic-gate 		if (minor_status != NULL)
7407c478bd9Sstevel@tonic-gate 			*minor_status = DEFAULT_MINOR_STAT;
7417c478bd9Sstevel@tonic-gate 		if (actual_mech_type != NULL)
7427c478bd9Sstevel@tonic-gate 			*actual_mech_type = NULL;
7437c478bd9Sstevel@tonic-gate 		if (output_token != NULL)
7447c478bd9Sstevel@tonic-gate 			output_token->length = 0;
7457c478bd9Sstevel@tonic-gate 		if (ret_flags != NULL)
7467c478bd9Sstevel@tonic-gate 			*ret_flags = 0;
7477c478bd9Sstevel@tonic-gate 		if (time_rec != NULL)
7487c478bd9Sstevel@tonic-gate 			*time_rec = 0;
7497c478bd9Sstevel@tonic-gate 
7507c478bd9Sstevel@tonic-gate 		killgssd_handle(clnt);
7517c478bd9Sstevel@tonic-gate 		(void) gss_release_buffer(&minor_status_temp, &external_name);
7527c478bd9Sstevel@tonic-gate 		GSSLOG0(1, "kgss_init_sec_context: RPC call times out\n");
7537c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
7547c478bd9Sstevel@tonic-gate 	}
7557c478bd9Sstevel@tonic-gate 
7567c478bd9Sstevel@tonic-gate 	/* free the allocated memory for the flattened name */
7577c478bd9Sstevel@tonic-gate 
7587c478bd9Sstevel@tonic-gate 	(void) gss_release_buffer(&minor_status_temp, &external_name);
7597c478bd9Sstevel@tonic-gate 
7607c478bd9Sstevel@tonic-gate 	if (minor_status != NULL)
7617c478bd9Sstevel@tonic-gate 		*minor_status = res.minor_status;
7627c478bd9Sstevel@tonic-gate 
763ba7b222eSGlenn Barry 	if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) {
764ba7b222eSGlenn Barry 		output_token->length =
765ba7b222eSGlenn Barry 		    (size_t)res.output_token.GSS_BUFFER_T_len;
766ba7b222eSGlenn Barry 		output_token->value =
767ba7b222eSGlenn Barry 		    (void *)MALLOC(output_token->length);
768ba7b222eSGlenn Barry 		(void) memcpy(output_token->value,
769*d4f95bf4SRichard Lowe 		    res.output_token.GSS_BUFFER_T_val, output_token->length);
770ba7b222eSGlenn Barry 	}
771ba7b222eSGlenn Barry 
7727c478bd9Sstevel@tonic-gate 	/* if the call was successful, copy out the results */
7737c478bd9Sstevel@tonic-gate 	if (res.status == (OM_uint32) GSS_S_COMPLETE ||
7747c478bd9Sstevel@tonic-gate 	    res.status == (OM_uint32) GSS_S_CONTINUE_NEEDED) {
7757c478bd9Sstevel@tonic-gate 		/*
7767c478bd9Sstevel@tonic-gate 		 * if the return code is GSS_S_CONTINUE_NEEDED
7777c478bd9Sstevel@tonic-gate 		 * ignore all return parameters except for
7787c478bd9Sstevel@tonic-gate 		 * status codes, output token and context handle.
7797c478bd9Sstevel@tonic-gate 		 */
7807c478bd9Sstevel@tonic-gate 		*context_handle =
781*d4f95bf4SRichard Lowe 		    *((gssd_ctx_id_t *)res.context_handle.GSS_CTX_ID_T_val);
7827c478bd9Sstevel@tonic-gate 		*gssd_context_verifier = res.gssd_context_verifier;
7837c478bd9Sstevel@tonic-gate 
7847c478bd9Sstevel@tonic-gate 		if (res.status == GSS_S_COMPLETE) {
7857c478bd9Sstevel@tonic-gate 			if (actual_mech_type != NULL) {
7867c478bd9Sstevel@tonic-gate 				*actual_mech_type =
7877c478bd9Sstevel@tonic-gate 				    (gss_OID) MALLOC(sizeof (gss_OID_desc));
7887c478bd9Sstevel@tonic-gate 				(*actual_mech_type)->length =
789*d4f95bf4SRichard Lowe 				    (OM_UINT32)res.actual_mech_type.GSS_OID_len;
7907c478bd9Sstevel@tonic-gate 				(*actual_mech_type)->elements =
791*d4f95bf4SRichard Lowe 				    (void *)MALLOC((*actual_mech_type)->length);
7927c478bd9Sstevel@tonic-gate 				(void) memcpy((*actual_mech_type)->elements,
793b97d6ca7SMilan Jurik 				    (void *)res.actual_mech_type.GSS_OID_val,
7947c478bd9Sstevel@tonic-gate 				    (*actual_mech_type)->length);
7957c478bd9Sstevel@tonic-gate 			}
7967c478bd9Sstevel@tonic-gate 
7977c478bd9Sstevel@tonic-gate 
7987c478bd9Sstevel@tonic-gate 			if (ret_flags != NULL)
7997c478bd9Sstevel@tonic-gate 				*ret_flags = res.ret_flags;
8007c478bd9Sstevel@tonic-gate 
8017c478bd9Sstevel@tonic-gate 			if (time_rec != NULL)
8027c478bd9Sstevel@tonic-gate 				*time_rec = res.time_rec;
8037c478bd9Sstevel@tonic-gate 		}
8047c478bd9Sstevel@tonic-gate 	}
8057c478bd9Sstevel@tonic-gate 
8067c478bd9Sstevel@tonic-gate 	/*
8077c478bd9Sstevel@tonic-gate 	 * free the memory allocated for the results and return with the status
8087c478bd9Sstevel@tonic-gate 	 * received in the rpc call
8097c478bd9Sstevel@tonic-gate 	 */
8107c478bd9Sstevel@tonic-gate 
8117c478bd9Sstevel@tonic-gate 	clnt_freeres(clnt, xdr_gss_init_sec_context_res, (caddr_t)&res);
8127c478bd9Sstevel@tonic-gate 	killgssd_handle(clnt);
8137c478bd9Sstevel@tonic-gate 	return (res.status);
8147c478bd9Sstevel@tonic-gate 
8157c478bd9Sstevel@tonic-gate }
8167c478bd9Sstevel@tonic-gate 
8177c478bd9Sstevel@tonic-gate static struct gss_config default_gc = {
8187c478bd9Sstevel@tonic-gate 	{ 0, NULL},
8197c478bd9Sstevel@tonic-gate 	NULL,
8207c478bd9Sstevel@tonic-gate 	NULL,
8217c478bd9Sstevel@tonic-gate 	0,
8227c478bd9Sstevel@tonic-gate 	kgss_unseal_wrapped,
8237c478bd9Sstevel@tonic-gate 	NULL,		/* kgss_delete_sec_context_wrapped */
8247c478bd9Sstevel@tonic-gate 	kgss_seal_wrapped,
8257c478bd9Sstevel@tonic-gate 	NULL,		/* kgss_import_sec_context */
8267c478bd9Sstevel@tonic-gate 	kgss_sign_wrapped,
8277c478bd9Sstevel@tonic-gate 	kgss_verify_wrapped
8287c478bd9Sstevel@tonic-gate };
8297c478bd9Sstevel@tonic-gate 
8307c478bd9Sstevel@tonic-gate void
8317c478bd9Sstevel@tonic-gate kgss_free_oid(gss_OID oid)
8327c478bd9Sstevel@tonic-gate {
8337c478bd9Sstevel@tonic-gate 	FREE(oid->elements, oid->length);
8347c478bd9Sstevel@tonic-gate 	FREE(oid, sizeof (gss_OID_desc));
8357c478bd9Sstevel@tonic-gate }
8367c478bd9Sstevel@tonic-gate 
8377c478bd9Sstevel@tonic-gate OM_uint32
8387c478bd9Sstevel@tonic-gate kgss_init_sec_context(
8397c478bd9Sstevel@tonic-gate 	OM_uint32 *minor_status,
8407c478bd9Sstevel@tonic-gate 	const gss_cred_id_t claimant_cred_handle,
8417c478bd9Sstevel@tonic-gate 	gss_ctx_id_t *context_handle,
8427c478bd9Sstevel@tonic-gate 	const gss_name_t target_name,
8437c478bd9Sstevel@tonic-gate 	const gss_OID mech_type,
8447c478bd9Sstevel@tonic-gate 	int req_flags,
8457c478bd9Sstevel@tonic-gate 	OM_uint32 time_req,
8467c478bd9Sstevel@tonic-gate 	const gss_channel_bindings_t input_chan_bindings,
8477c478bd9Sstevel@tonic-gate 	const gss_buffer_t input_token,
8487c478bd9Sstevel@tonic-gate 	gss_OID *actual_mech_type,
8497c478bd9Sstevel@tonic-gate 	gss_buffer_t output_token,
8507c478bd9Sstevel@tonic-gate 	int *ret_flags,
8517c478bd9Sstevel@tonic-gate 	OM_uint32 *time_rec,
8527c478bd9Sstevel@tonic-gate 	uid_t uid)
8537c478bd9Sstevel@tonic-gate {
8547c478bd9Sstevel@tonic-gate 	OM_uint32	err;
8557c478bd9Sstevel@tonic-gate 	struct kgss_ctx	*kctx;
8567c478bd9Sstevel@tonic-gate 	gss_OID	amt;
8577c478bd9Sstevel@tonic-gate 	gssd_cred_id_t gssd_cl_cred_handle;
8587c478bd9Sstevel@tonic-gate 	OM_uint32 gssd_cred_verifier;
8597c478bd9Sstevel@tonic-gate 
8607c478bd9Sstevel@tonic-gate 	/*
8617c478bd9Sstevel@tonic-gate 	 * If this is an initial call, we'll need to create the
8627c478bd9Sstevel@tonic-gate 	 * wrapper struct that contains kernel state information, and
8637c478bd9Sstevel@tonic-gate 	 * a reference to the handle from gssd.
8647c478bd9Sstevel@tonic-gate 	 */
8657c478bd9Sstevel@tonic-gate 	if (*context_handle == GSS_C_NO_CONTEXT) {
8667c478bd9Sstevel@tonic-gate 		kctx = KGSS_ALLOC();
8677c478bd9Sstevel@tonic-gate 		/*
8687c478bd9Sstevel@tonic-gate 		 * The default gss-mechanism struct as pointers to
8697c478bd9Sstevel@tonic-gate 		 * the sign/seal/verify/unseal routines that make
8707c478bd9Sstevel@tonic-gate 		 * upcalls to gssd.
8717c478bd9Sstevel@tonic-gate 		 */
8727c478bd9Sstevel@tonic-gate 		kctx->mech = &default_gc;
873*d4f95bf4SRichard Lowe 		kctx->gssd_ctx = GSSD_NO_CONTEXT;
8747c478bd9Sstevel@tonic-gate 		*context_handle = (gss_ctx_id_t)kctx;
8757c478bd9Sstevel@tonic-gate 	} else
8767c478bd9Sstevel@tonic-gate 		kctx = (struct kgss_ctx *)*context_handle;
8777c478bd9Sstevel@tonic-gate 
8787c478bd9Sstevel@tonic-gate 	if (claimant_cred_handle != GSS_C_NO_CREDENTIAL) {
8797c478bd9Sstevel@tonic-gate 		gssd_cred_verifier = KCRED_TO_CREDV(claimant_cred_handle);
8807c478bd9Sstevel@tonic-gate 		gssd_cl_cred_handle = KCRED_TO_CRED(claimant_cred_handle);
881*d4f95bf4SRichard Lowe 	} else {
882*d4f95bf4SRichard Lowe 		gssd_cl_cred_handle = GSSD_NO_CREDENTIAL;
883*d4f95bf4SRichard Lowe 	}
8847c478bd9Sstevel@tonic-gate 
8857c478bd9Sstevel@tonic-gate 	/*
8867c478bd9Sstevel@tonic-gate 	 * We need to know the resulting mechanism oid, so allocate
8877c478bd9Sstevel@tonic-gate 	 * it if the caller won't.
8887c478bd9Sstevel@tonic-gate 	 */
8897c478bd9Sstevel@tonic-gate 	if (actual_mech_type == NULL)
8907c478bd9Sstevel@tonic-gate 		actual_mech_type = &amt;
8917c478bd9Sstevel@tonic-gate 
8927c478bd9Sstevel@tonic-gate 	err = kgss_init_sec_context_wrapped(minor_status, gssd_cl_cred_handle,
8937c478bd9Sstevel@tonic-gate 	    gssd_cred_verifier, &kctx->gssd_ctx, &kctx->gssd_ctx_verifier,
8947c478bd9Sstevel@tonic-gate 	    target_name, mech_type, req_flags, time_req,
8957c478bd9Sstevel@tonic-gate 	    input_chan_bindings, input_token, actual_mech_type,
8967c478bd9Sstevel@tonic-gate 	    output_token, ret_flags, time_rec, uid);
8977c478bd9Sstevel@tonic-gate 
8987c478bd9Sstevel@tonic-gate 	if (GSS_ERROR(err)) {
8997c478bd9Sstevel@tonic-gate 		KGSS_FREE(kctx);
9007c478bd9Sstevel@tonic-gate 		*context_handle = GSS_C_NO_CONTEXT;
9017c478bd9Sstevel@tonic-gate 	} else if (err == GSS_S_COMPLETE) {
9027c478bd9Sstevel@tonic-gate 		/*
9037c478bd9Sstevel@tonic-gate 		 * Now check if there is a kernel module for this
9047c478bd9Sstevel@tonic-gate 		 * mechanism OID. If so, set the gss_mechanism structure
9057c478bd9Sstevel@tonic-gate 		 * in the wrapper context to point to the kernel mech.
9067c478bd9Sstevel@tonic-gate 		 */
9077c478bd9Sstevel@tonic-gate 		__kgss_reset_mech(&kctx->mech, *actual_mech_type);
9087c478bd9Sstevel@tonic-gate 
9097c478bd9Sstevel@tonic-gate 		/*
9107c478bd9Sstevel@tonic-gate 		 * If the mech oid was allocated for us, free it.
9117c478bd9Sstevel@tonic-gate 		 */
9127c478bd9Sstevel@tonic-gate 		if (&amt == actual_mech_type) {
9137c478bd9Sstevel@tonic-gate 			kgss_free_oid(amt);
9147c478bd9Sstevel@tonic-gate 		}
9157c478bd9Sstevel@tonic-gate 	}
9167c478bd9Sstevel@tonic-gate 	return (err);
9177c478bd9Sstevel@tonic-gate }
9187c478bd9Sstevel@tonic-gate 
9197c478bd9Sstevel@tonic-gate static OM_uint32
9207c478bd9Sstevel@tonic-gate kgss_accept_sec_context_wrapped(
9217c478bd9Sstevel@tonic-gate 	OM_uint32 *minor_status,
9227c478bd9Sstevel@tonic-gate 	gssd_ctx_id_t *context_handle,
9237c478bd9Sstevel@tonic-gate 	OM_uint32 *gssd_context_verifier,
9247c478bd9Sstevel@tonic-gate 	const gssd_cred_id_t verifier_cred_handle,
9257c478bd9Sstevel@tonic-gate 	OM_uint32 gssd_cred_verifier,
9267c478bd9Sstevel@tonic-gate 	const gss_buffer_t input_token,
9277c478bd9Sstevel@tonic-gate 	const gss_channel_bindings_t input_chan_bindings,
9287c478bd9Sstevel@tonic-gate 	gss_buffer_t src_name,
9297c478bd9Sstevel@tonic-gate 	gss_OID *mech_type,
9307c478bd9Sstevel@tonic-gate 	gss_buffer_t output_token,
9317c478bd9Sstevel@tonic-gate 	int *ret_flags,
9327c478bd9Sstevel@tonic-gate 	OM_uint32 *time_rec,
9337c478bd9Sstevel@tonic-gate 	gss_cred_id_t *delegated_cred_handle,
9347c478bd9Sstevel@tonic-gate 	uid_t uid)
9357c478bd9Sstevel@tonic-gate {
9367c478bd9Sstevel@tonic-gate 	CLIENT *clnt;
9377c478bd9Sstevel@tonic-gate 
9387c478bd9Sstevel@tonic-gate 	gss_accept_sec_context_arg arg;
9397c478bd9Sstevel@tonic-gate 	gss_accept_sec_context_res res;
9407c478bd9Sstevel@tonic-gate 	struct kgss_cred *kcred;
9417c478bd9Sstevel@tonic-gate 
9427c478bd9Sstevel@tonic-gate 	/* get the client handle to GSSD */
9437c478bd9Sstevel@tonic-gate 
9447c478bd9Sstevel@tonic-gate 	if ((clnt = getgssd_handle()) == NULL) {
9457c478bd9Sstevel@tonic-gate 		GSSLOG(1,
9467c478bd9Sstevel@tonic-gate 		    "kgss_accept_sec_context: can't connect to server on %s\n",
9477c478bd9Sstevel@tonic-gate 		    server);
9487c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
9497c478bd9Sstevel@tonic-gate 	}
9507c478bd9Sstevel@tonic-gate 
9517c478bd9Sstevel@tonic-gate 	/* copy the procedure arguments into the rpc arg parameter */
9527c478bd9Sstevel@tonic-gate 
9537c478bd9Sstevel@tonic-gate 	arg.uid = (OM_uint32)uid;
9547c478bd9Sstevel@tonic-gate 
9557c478bd9Sstevel@tonic-gate 	arg.context_handle.GSS_CTX_ID_T_len =
956*d4f95bf4SRichard Lowe 	    *context_handle == GSSD_NO_CONTEXT ?
9577c478bd9Sstevel@tonic-gate 	    0 : (uint_t)sizeof (gssd_ctx_id_t);
9587c478bd9Sstevel@tonic-gate 	arg.context_handle.GSS_CTX_ID_T_val =  (char *)context_handle;
9597c478bd9Sstevel@tonic-gate 	arg.gssd_context_verifier = *gssd_context_verifier;
9607c478bd9Sstevel@tonic-gate 
9617c478bd9Sstevel@tonic-gate 	arg.verifier_cred_handle.GSS_CRED_ID_T_len =
962*d4f95bf4SRichard Lowe 	    verifier_cred_handle == GSSD_NO_CREDENTIAL ?
9637c478bd9Sstevel@tonic-gate 	    0 : (uint_t)sizeof (gssd_cred_id_t);
9647c478bd9Sstevel@tonic-gate 	arg.verifier_cred_handle.GSS_CRED_ID_T_val =
9657c478bd9Sstevel@tonic-gate 	    (char *)&verifier_cred_handle;
9667c478bd9Sstevel@tonic-gate 	arg.gssd_cred_verifier = gssd_cred_verifier;
9677c478bd9Sstevel@tonic-gate 
9687c478bd9Sstevel@tonic-gate 	arg.input_token_buffer.GSS_BUFFER_T_len =
969*d4f95bf4SRichard Lowe 	    (uint_t)(input_token != GSS_C_NO_BUFFER ? input_token->length : 0);
9707c478bd9Sstevel@tonic-gate 	arg.input_token_buffer.GSS_BUFFER_T_val =
971*d4f95bf4SRichard Lowe 	    (char *)(input_token != GSS_C_NO_BUFFER ? input_token->value : 0);
9727c478bd9Sstevel@tonic-gate 
9737c478bd9Sstevel@tonic-gate 	if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) {
9747c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.present = YES;
9757c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.initiator_addrtype =
9767c478bd9Sstevel@tonic-gate 		    input_chan_bindings->initiator_addrtype;
9777c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len =
9787c478bd9Sstevel@tonic-gate 		    (uint_t)input_chan_bindings->initiator_address.length;
9797c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val =
9807c478bd9Sstevel@tonic-gate 		    (void *)input_chan_bindings->initiator_address.value;
9817c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.acceptor_addrtype =
9827c478bd9Sstevel@tonic-gate 		    input_chan_bindings->acceptor_addrtype;
9837c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len =
9847c478bd9Sstevel@tonic-gate 		    (uint_t)input_chan_bindings->acceptor_address.length;
9857c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val =
9867c478bd9Sstevel@tonic-gate 		    (void *)input_chan_bindings->acceptor_address.value;
9877c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.application_data.GSS_BUFFER_T_len =
9887c478bd9Sstevel@tonic-gate 		    (uint_t)input_chan_bindings->application_data.length;
9897c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.application_data.GSS_BUFFER_T_val =
9907c478bd9Sstevel@tonic-gate 		    (void *)input_chan_bindings->application_data.value;
9917c478bd9Sstevel@tonic-gate 	} else {
9927c478bd9Sstevel@tonic-gate 
9937c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.present = NO;
9947c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.initiator_addrtype = 0;
9957c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = 0;
9967c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = 0;
9977c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.acceptor_addrtype = 0;
9987c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = 0;
9997c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = 0;
10007c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = 0;
10017c478bd9Sstevel@tonic-gate 		arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = 0;
10027c478bd9Sstevel@tonic-gate 	}
10037c478bd9Sstevel@tonic-gate 
10047c478bd9Sstevel@tonic-gate 	/* set the return parameters in case of errors.... */
10057c478bd9Sstevel@tonic-gate 	if (minor_status != NULL)
10067c478bd9Sstevel@tonic-gate 		*minor_status = DEFAULT_MINOR_STAT;
10077c478bd9Sstevel@tonic-gate 	if (src_name != NULL) {
10087c478bd9Sstevel@tonic-gate 		src_name->length = 0;
10097c478bd9Sstevel@tonic-gate 		src_name->value = NULL;
10107c478bd9Sstevel@tonic-gate 	}
10117c478bd9Sstevel@tonic-gate 	if (mech_type != NULL)
10127c478bd9Sstevel@tonic-gate 		*mech_type = NULL;
10137c478bd9Sstevel@tonic-gate 	if (output_token != NULL)
10147c478bd9Sstevel@tonic-gate 		output_token->length = 0;
10157c478bd9Sstevel@tonic-gate 	if (ret_flags != NULL)
10167c478bd9Sstevel@tonic-gate 		*ret_flags = 0;
10177c478bd9Sstevel@tonic-gate 	if (time_rec != NULL)
10187c478bd9Sstevel@tonic-gate 		*time_rec = 0;
10197c478bd9Sstevel@tonic-gate 	if (delegated_cred_handle != NULL)
10207c478bd9Sstevel@tonic-gate 		*delegated_cred_handle = NULL;
10217c478bd9Sstevel@tonic-gate 
10227c478bd9Sstevel@tonic-gate 	/* call the remote procedure */
10237c478bd9Sstevel@tonic-gate 
10247c478bd9Sstevel@tonic-gate 	bzero((caddr_t)&res, sizeof (res));
10257c478bd9Sstevel@tonic-gate 	if (gss_accept_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
10267c478bd9Sstevel@tonic-gate 		killgssd_handle(clnt);
10277c478bd9Sstevel@tonic-gate 		GSSLOG0(1, "kgss_accept_sec_context: RPC call times out\n");
10287c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
10297c478bd9Sstevel@tonic-gate 	}
10307c478bd9Sstevel@tonic-gate 
1031ba7b222eSGlenn Barry 	if (minor_status != NULL)
1032ba7b222eSGlenn Barry 		*minor_status = res.minor_status;
1033ba7b222eSGlenn Barry 
1034ba7b222eSGlenn Barry 	if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) {
1035*d4f95bf4SRichard Lowe 		output_token->length = res.output_token.GSS_BUFFER_T_len;
1036*d4f95bf4SRichard Lowe 		output_token->value = (void *)MALLOC(output_token->length);
1037ba7b222eSGlenn Barry 		(void) memcpy(output_token->value,
1038*d4f95bf4SRichard Lowe 		    res.output_token.GSS_BUFFER_T_val, output_token->length);
1039ba7b222eSGlenn Barry 	}
1040ba7b222eSGlenn Barry 
10417c478bd9Sstevel@tonic-gate 	/* if the call was successful, copy out the results */
10427c478bd9Sstevel@tonic-gate 
10437c478bd9Sstevel@tonic-gate 	if (res.status == (OM_uint32)GSS_S_COMPLETE ||
10447c478bd9Sstevel@tonic-gate 	    res.status == (OM_uint32)GSS_S_CONTINUE_NEEDED) {
10457c478bd9Sstevel@tonic-gate 
10467c478bd9Sstevel@tonic-gate 		/*
10477c478bd9Sstevel@tonic-gate 		 * the only parameters that are ready when we
10487c478bd9Sstevel@tonic-gate 		 * get GSS_S_CONTINUE_NEEDED are: minor, ctxt_handle,
10497c478bd9Sstevel@tonic-gate 		 * and the output token to send to the peer.
10507c478bd9Sstevel@tonic-gate 		 */
10517c478bd9Sstevel@tonic-gate 
10527c478bd9Sstevel@tonic-gate 		*context_handle = *((gssd_ctx_id_t *)
10537c478bd9Sstevel@tonic-gate 		    res.context_handle.GSS_CTX_ID_T_val);
10547c478bd9Sstevel@tonic-gate 		*gssd_context_verifier = res.gssd_context_verifier;
10557c478bd9Sstevel@tonic-gate 
10567c478bd9Sstevel@tonic-gate 		/* these other parameters are only ready upon GSS_S_COMPLETE */
10577c478bd9Sstevel@tonic-gate 		if (res.status == (OM_uint32)GSS_S_COMPLETE) {
10587c478bd9Sstevel@tonic-gate 
10597c478bd9Sstevel@tonic-gate 			if (src_name != NULL) {
1060b97d6ca7SMilan Jurik 				src_name->length =
1061b97d6ca7SMilan Jurik 				    res.src_name.GSS_BUFFER_T_len;
10627c478bd9Sstevel@tonic-gate 				src_name->value = res.src_name.GSS_BUFFER_T_val;
10637c478bd9Sstevel@tonic-gate 				res.src_name.GSS_BUFFER_T_val = NULL;
10647c478bd9Sstevel@tonic-gate 				res.src_name.GSS_BUFFER_T_len = 0;
10657c478bd9Sstevel@tonic-gate 			}
10667c478bd9Sstevel@tonic-gate 
10677c478bd9Sstevel@tonic-gate 			/*
10687c478bd9Sstevel@tonic-gate 			 * move mech type returned to mech_type
10697c478bd9Sstevel@tonic-gate 			 * for gss_import_name_for_mech()
10707c478bd9Sstevel@tonic-gate 			 */
10717c478bd9Sstevel@tonic-gate 			if (mech_type != NULL) {
1072*d4f95bf4SRichard Lowe 				*mech_type =
1073*d4f95bf4SRichard Lowe 				    (gss_OID)MALLOC(sizeof (gss_OID_desc));
10747c478bd9Sstevel@tonic-gate 				(*mech_type)->length =
10757c478bd9Sstevel@tonic-gate 				    (OM_UINT32)res.mech_type.GSS_OID_len;
10767c478bd9Sstevel@tonic-gate 				(*mech_type)->elements =
10777c478bd9Sstevel@tonic-gate 				    (void *)MALLOC((*mech_type)->length);
10787c478bd9Sstevel@tonic-gate 				(void) memcpy((*mech_type)->elements,
10797c478bd9Sstevel@tonic-gate 				    res.mech_type.GSS_OID_val,
10807c478bd9Sstevel@tonic-gate 				    (*mech_type)->length);
10817c478bd9Sstevel@tonic-gate 			}
10827c478bd9Sstevel@tonic-gate 
10837c478bd9Sstevel@tonic-gate 			if (ret_flags != NULL)
10847c478bd9Sstevel@tonic-gate 				*ret_flags = res.ret_flags;
10857c478bd9Sstevel@tonic-gate 
10867c478bd9Sstevel@tonic-gate 			if (time_rec != NULL)
10877c478bd9Sstevel@tonic-gate 				*time_rec = res.time_rec;
10887c478bd9Sstevel@tonic-gate 
10897c478bd9Sstevel@tonic-gate 			if ((delegated_cred_handle != NULL) &&
10907c478bd9Sstevel@tonic-gate 			    (res.delegated_cred_handle.GSS_CRED_ID_T_len
10917c478bd9Sstevel@tonic-gate 			    != 0)) {
10927c478bd9Sstevel@tonic-gate 				kcred = KGSS_CRED_ALLOC();
1093*d4f95bf4SRichard Lowe 				kcred->gssd_cred =
1094*d4f95bf4SRichard Lowe 				    *((gssd_cred_id_t *)
10957c478bd9Sstevel@tonic-gate 				    res.delegated_cred_handle.GSS_CRED_ID_T_val);
10967c478bd9Sstevel@tonic-gate 				kcred->gssd_cred_verifier =
10977c478bd9Sstevel@tonic-gate 				    res.gssd_context_verifier;
10987c478bd9Sstevel@tonic-gate 				*delegated_cred_handle = (gss_cred_id_t)kcred;
10997c478bd9Sstevel@tonic-gate 			}
11007c478bd9Sstevel@tonic-gate 
11017c478bd9Sstevel@tonic-gate 		}
11027c478bd9Sstevel@tonic-gate 	}
11037c478bd9Sstevel@tonic-gate 
11047c478bd9Sstevel@tonic-gate 
11057c478bd9Sstevel@tonic-gate 	/*
11067c478bd9Sstevel@tonic-gate 	 * free the memory allocated for the results and return with the status
11077c478bd9Sstevel@tonic-gate 	 * received in the rpc call
11087c478bd9Sstevel@tonic-gate 	 */
11097c478bd9Sstevel@tonic-gate 
11107c478bd9Sstevel@tonic-gate 	clnt_freeres(clnt, xdr_gss_accept_sec_context_res, (caddr_t)&res);
11117c478bd9Sstevel@tonic-gate 	killgssd_handle(clnt);
11127c478bd9Sstevel@tonic-gate 	return (res.status);
11137c478bd9Sstevel@tonic-gate 
11147c478bd9Sstevel@tonic-gate }
11157c478bd9Sstevel@tonic-gate 
11167c478bd9Sstevel@tonic-gate OM_uint32
11177c478bd9Sstevel@tonic-gate kgss_accept_sec_context(
11187c478bd9Sstevel@tonic-gate 	OM_uint32 *minor_status,
11197c478bd9Sstevel@tonic-gate 	gss_ctx_id_t *context_handle,
11207c478bd9Sstevel@tonic-gate 	const gss_cred_id_t verifier_cred_handle,
11217c478bd9Sstevel@tonic-gate 	const gss_buffer_t input_token,
11227c478bd9Sstevel@tonic-gate 	const gss_channel_bindings_t input_chan_bindings,
11237c478bd9Sstevel@tonic-gate 	gss_buffer_t src_name,
11247c478bd9Sstevel@tonic-gate 	gss_OID *mech_type,
11257c478bd9Sstevel@tonic-gate 	gss_buffer_t output_token,
11267c478bd9Sstevel@tonic-gate 	int *ret_flags,
11277c478bd9Sstevel@tonic-gate 	OM_uint32 *time_rec,
11287c478bd9Sstevel@tonic-gate 	gss_cred_id_t *delegated_cred_handle,
11297c478bd9Sstevel@tonic-gate 	uid_t uid)
11307c478bd9Sstevel@tonic-gate {
11317c478bd9Sstevel@tonic-gate 	OM_uint32 err;
11327c478bd9Sstevel@tonic-gate 	struct kgss_ctx	*kctx;
11337c478bd9Sstevel@tonic-gate 	gss_OID mt;
11347c478bd9Sstevel@tonic-gate 	OM_uint32 gssd_cred_verifier;
11357c478bd9Sstevel@tonic-gate 	gssd_cred_id_t gssd_ver_cred_handle;
11367c478bd9Sstevel@tonic-gate 
11377c478bd9Sstevel@tonic-gate 
11387c478bd9Sstevel@tonic-gate 	/*
11397c478bd9Sstevel@tonic-gate 	 * See kgss_init_sec_context() to get an idea of what is going
11407c478bd9Sstevel@tonic-gate 	 * on here.
11417c478bd9Sstevel@tonic-gate 	 */
11427c478bd9Sstevel@tonic-gate 	if (mech_type == NULL)
11437c478bd9Sstevel@tonic-gate 		mech_type = &mt;
11447c478bd9Sstevel@tonic-gate 
11457c478bd9Sstevel@tonic-gate 	if (*context_handle == GSS_C_NO_CONTEXT) {
11467c478bd9Sstevel@tonic-gate 		kctx = KGSS_ALLOC();
11477c478bd9Sstevel@tonic-gate 		kctx->mech = &default_gc;
1148*d4f95bf4SRichard Lowe 		kctx->gssd_ctx = GSSD_NO_CONTEXT;
11497c478bd9Sstevel@tonic-gate 		*context_handle = (gss_ctx_id_t)kctx;
11507c478bd9Sstevel@tonic-gate 	} else
11517c478bd9Sstevel@tonic-gate 		kctx = (struct kgss_ctx *)*context_handle;
11527c478bd9Sstevel@tonic-gate 
11537c478bd9Sstevel@tonic-gate 	if (verifier_cred_handle != GSS_C_NO_CREDENTIAL) {
11547c478bd9Sstevel@tonic-gate 		gssd_cred_verifier = KCRED_TO_CREDV(verifier_cred_handle);
11557c478bd9Sstevel@tonic-gate 		gssd_ver_cred_handle = KCRED_TO_CRED(verifier_cred_handle);
1156*d4f95bf4SRichard Lowe 	} else {
1157*d4f95bf4SRichard Lowe 		gssd_ver_cred_handle = GSSD_NO_CREDENTIAL;
1158*d4f95bf4SRichard Lowe 	}
11597c478bd9Sstevel@tonic-gate 
11607c478bd9Sstevel@tonic-gate 	err = kgss_accept_sec_context_wrapped(minor_status,
11617c478bd9Sstevel@tonic-gate 	    &kctx->gssd_ctx, &kctx->gssd_ctx_verifier,
11627c478bd9Sstevel@tonic-gate 	    gssd_ver_cred_handle, gssd_cred_verifier,
11637c478bd9Sstevel@tonic-gate 	    input_token, input_chan_bindings, src_name,
11647c478bd9Sstevel@tonic-gate 	    mech_type, output_token, ret_flags,
11657c478bd9Sstevel@tonic-gate 	    time_rec, delegated_cred_handle, uid);
11667c478bd9Sstevel@tonic-gate 
11677c478bd9Sstevel@tonic-gate 	if (GSS_ERROR(err)) {
11687c478bd9Sstevel@tonic-gate 		KGSS_FREE(kctx);
11697c478bd9Sstevel@tonic-gate 		*context_handle = GSS_C_NO_CONTEXT;
11707c478bd9Sstevel@tonic-gate 
11717c478bd9Sstevel@tonic-gate 	} else if (err == GSS_S_COMPLETE) {
11727c478bd9Sstevel@tonic-gate 		__kgss_reset_mech(&kctx->mech, *mech_type);
11737c478bd9Sstevel@tonic-gate 
11747c478bd9Sstevel@tonic-gate 		/*
11757c478bd9Sstevel@tonic-gate 		 * If the mech oid was allocated for us, free it.
11767c478bd9Sstevel@tonic-gate 		 */
11777c478bd9Sstevel@tonic-gate 		if (&mt == mech_type) {
11787c478bd9Sstevel@tonic-gate 			kgss_free_oid(mt);
11797c478bd9Sstevel@tonic-gate 		}
11807c478bd9Sstevel@tonic-gate 	}
11817c478bd9Sstevel@tonic-gate 
11827c478bd9Sstevel@tonic-gate 	return (err);
11837c478bd9Sstevel@tonic-gate }
11847c478bd9Sstevel@tonic-gate 
11857c478bd9Sstevel@tonic-gate OM_uint32
11867c478bd9Sstevel@tonic-gate kgss_process_context_token(minor_status,
11877c478bd9Sstevel@tonic-gate 				context_handle,
11887c478bd9Sstevel@tonic-gate 				token_buffer,
11897c478bd9Sstevel@tonic-gate 				uid)
11907c478bd9Sstevel@tonic-gate 	OM_uint32 *minor_status;
11917c478bd9Sstevel@tonic-gate 	const gss_ctx_id_t context_handle;
11927c478bd9Sstevel@tonic-gate 	gss_buffer_t token_buffer;
11937c478bd9Sstevel@tonic-gate 	uid_t uid;
11947c478bd9Sstevel@tonic-gate {
11957c478bd9Sstevel@tonic-gate 	CLIENT *clnt;
11967c478bd9Sstevel@tonic-gate 	OM_uint32 gssd_context_verifier;
11977c478bd9Sstevel@tonic-gate 	gssd_ctx_id_t gssd_ctx_handle;
11987c478bd9Sstevel@tonic-gate 	gss_process_context_token_arg arg;
11997c478bd9Sstevel@tonic-gate 	gss_process_context_token_res res;
12007c478bd9Sstevel@tonic-gate 
12017c478bd9Sstevel@tonic-gate 	gssd_context_verifier = KGSS_CTX_TO_GSSD_CTXV(context_handle);
12027c478bd9Sstevel@tonic-gate 	gssd_ctx_handle = (gssd_ctx_id_t)KGSS_CTX_TO_GSSD_CTX(context_handle);
12037c478bd9Sstevel@tonic-gate 
12047c478bd9Sstevel@tonic-gate 	/* get the client handle to GSSD */
12057c478bd9Sstevel@tonic-gate 
12067c478bd9Sstevel@tonic-gate 	if ((clnt = getgssd_handle()) == NULL) {
12077c478bd9Sstevel@tonic-gate 		GSSLOG(1,
12087c478bd9Sstevel@tonic-gate 		"kgss_process_context_token: can't connect to server on %s\n",
12097c478bd9Sstevel@tonic-gate 		server);
12107c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
12117c478bd9Sstevel@tonic-gate 	}
12127c478bd9Sstevel@tonic-gate 
12137c478bd9Sstevel@tonic-gate 	/* copy the procedure arguments into the rpc arg parameter */
12147c478bd9Sstevel@tonic-gate 
12157c478bd9Sstevel@tonic-gate 	arg.uid = (OM_uint32) uid;
12167c478bd9Sstevel@tonic-gate 
12177c478bd9Sstevel@tonic-gate 	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
12187c478bd9Sstevel@tonic-gate 	arg.context_handle.GSS_CTX_ID_T_val = (char *)&gssd_ctx_handle;
12197c478bd9Sstevel@tonic-gate 	arg.gssd_context_verifier = gssd_context_verifier;
12207c478bd9Sstevel@tonic-gate 	arg.token_buffer.GSS_BUFFER_T_len = (uint_t)token_buffer->length;
12217c478bd9Sstevel@tonic-gate 	arg.token_buffer.GSS_BUFFER_T_val = (char *)token_buffer->value;
12227c478bd9Sstevel@tonic-gate 
12237c478bd9Sstevel@tonic-gate 	/* call the remote procedure */
12247c478bd9Sstevel@tonic-gate 
12257c478bd9Sstevel@tonic-gate 	bzero(&res, sizeof (res));
12267c478bd9Sstevel@tonic-gate 
12277c478bd9Sstevel@tonic-gate 	if (gss_process_context_token_1(&arg, &res, clnt) != RPC_SUCCESS) {
12287c478bd9Sstevel@tonic-gate 
12297c478bd9Sstevel@tonic-gate 	/*
12307c478bd9Sstevel@tonic-gate 	 * if the RPC call times out, null out all return arguments, set
12317c478bd9Sstevel@tonic-gate 	 * minor_status to its maximum value, and return GSS_S_FAILURE
12327c478bd9Sstevel@tonic-gate 	 */
12337c478bd9Sstevel@tonic-gate 
12347c478bd9Sstevel@tonic-gate 		if (minor_status != NULL)
12357c478bd9Sstevel@tonic-gate 			*minor_status = DEFAULT_MINOR_STAT;
12367c478bd9Sstevel@tonic-gate 		GSSLOG0(1, "kgss_process_context_token: RPC call times out\n");
12377c478bd9Sstevel@tonic-gate 		killgssd_handle(clnt);
12387c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
12397c478bd9Sstevel@tonic-gate 	}
12407c478bd9Sstevel@tonic-gate 
12417c478bd9Sstevel@tonic-gate 	/* copy the rpc results into the return arguments */
12427c478bd9Sstevel@tonic-gate 
12437c478bd9Sstevel@tonic-gate 	if (minor_status != NULL)
12447c478bd9Sstevel@tonic-gate 		*minor_status = res.minor_status;
12457c478bd9Sstevel@tonic-gate 
12467c478bd9Sstevel@tonic-gate 	/* return with status returned in rpc call */
12477c478bd9Sstevel@tonic-gate 
12487c478bd9Sstevel@tonic-gate 	killgssd_handle(clnt);
12497c478bd9Sstevel@tonic-gate 	return (res.status);
12507c478bd9Sstevel@tonic-gate 
12517c478bd9Sstevel@tonic-gate }
12527c478bd9Sstevel@tonic-gate 
12537c478bd9Sstevel@tonic-gate /*ARGSUSED*/
12547c478bd9Sstevel@tonic-gate static OM_uint32
12557c478bd9Sstevel@tonic-gate kgss_delete_sec_context_wrapped(void *private,
12567c478bd9Sstevel@tonic-gate 			OM_uint32 *minor_status,
12577c478bd9Sstevel@tonic-gate 			gssd_ctx_id_t *context_handle,
12587c478bd9Sstevel@tonic-gate 			gss_buffer_t output_token,
12597c478bd9Sstevel@tonic-gate 			OM_uint32 gssd_context_verifier)
12607c478bd9Sstevel@tonic-gate 
12617c478bd9Sstevel@tonic-gate 
12627c478bd9Sstevel@tonic-gate {
12637c478bd9Sstevel@tonic-gate 	CLIENT *clnt;
12647c478bd9Sstevel@tonic-gate 
12657c478bd9Sstevel@tonic-gate 	gss_delete_sec_context_arg arg;
12667c478bd9Sstevel@tonic-gate 	gss_delete_sec_context_res res;
12677c478bd9Sstevel@tonic-gate 
12687c478bd9Sstevel@tonic-gate 
12697c478bd9Sstevel@tonic-gate 	/* get the client handle to GSSD */
12707c478bd9Sstevel@tonic-gate 
12717c478bd9Sstevel@tonic-gate 	if ((clnt = getgssd_handle()) == NULL) {
12727c478bd9Sstevel@tonic-gate 		GSSLOG(1,
12737c478bd9Sstevel@tonic-gate 		"kgss_delete_sec_context: can't connect to server on %s\n",
12747c478bd9Sstevel@tonic-gate 		server);
12757c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
12767c478bd9Sstevel@tonic-gate 	}
12777c478bd9Sstevel@tonic-gate 
12787c478bd9Sstevel@tonic-gate 	/* copy the procedure arguments into the rpc arg parameter */
12797c478bd9Sstevel@tonic-gate 
12807c478bd9Sstevel@tonic-gate 	arg.context_handle.GSS_CTX_ID_T_len =
1281*d4f95bf4SRichard Lowe 		*context_handle == GSSD_NO_CONTEXT ?
12827c478bd9Sstevel@tonic-gate 			0 : (uint_t)sizeof (gssd_ctx_id_t);
12837c478bd9Sstevel@tonic-gate 	arg.context_handle.GSS_CTX_ID_T_val =  (char *)context_handle;
12847c478bd9Sstevel@tonic-gate 
12857c478bd9Sstevel@tonic-gate 	arg.gssd_context_verifier = gssd_context_verifier;
12867c478bd9Sstevel@tonic-gate 
12877c478bd9Sstevel@tonic-gate 	/* call the remote procedure */
12887c478bd9Sstevel@tonic-gate 
12897c478bd9Sstevel@tonic-gate 	bzero((caddr_t)&res, sizeof (res));
12907c478bd9Sstevel@tonic-gate 	if (gss_delete_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
12917c478bd9Sstevel@tonic-gate 
12927c478bd9Sstevel@tonic-gate 	/*
12937c478bd9Sstevel@tonic-gate 	 * if the RPC call times out, null out all return arguments, set
12947c478bd9Sstevel@tonic-gate 	 * minor_status to its maximum value, and return GSS_S_FAILURE
12957c478bd9Sstevel@tonic-gate 	 */
12967c478bd9Sstevel@tonic-gate 
12977c478bd9Sstevel@tonic-gate 		if (minor_status != NULL)
12987c478bd9Sstevel@tonic-gate 			*minor_status = DEFAULT_MINOR_STAT;
12997c478bd9Sstevel@tonic-gate 		if (context_handle != NULL)
13007c478bd9Sstevel@tonic-gate 			*context_handle = NULL;
13017c478bd9Sstevel@tonic-gate 		if (output_token != NULL)
13027c478bd9Sstevel@tonic-gate 			output_token->length = 0;
13037c478bd9Sstevel@tonic-gate 
13047c478bd9Sstevel@tonic-gate 		killgssd_handle(clnt);
13057c478bd9Sstevel@tonic-gate 		GSSLOG0(1, "kgssd_delete_sec_context: RPC call times out\n");
13067c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
13077c478bd9Sstevel@tonic-gate 	}
13087c478bd9Sstevel@tonic-gate 
13097c478bd9Sstevel@tonic-gate 	/* copy the rpc results into the return arguments */
13107c478bd9Sstevel@tonic-gate 
13117c478bd9Sstevel@tonic-gate 	if (minor_status != NULL)
13127c478bd9Sstevel@tonic-gate 		*minor_status = res.minor_status;
13137c478bd9Sstevel@tonic-gate 
13147c478bd9Sstevel@tonic-gate 	if (res.context_handle.GSS_CTX_ID_T_len == 0)
13157c478bd9Sstevel@tonic-gate 		*context_handle = NULL;
13167c478bd9Sstevel@tonic-gate 	else
13177c478bd9Sstevel@tonic-gate 		*context_handle =
13187c478bd9Sstevel@tonic-gate 		    *((gssd_ctx_id_t *)res.context_handle.GSS_CTX_ID_T_val);
13197c478bd9Sstevel@tonic-gate 
13207c478bd9Sstevel@tonic-gate 	if (output_token != NULL) {
13217c478bd9Sstevel@tonic-gate 		output_token->length = res.output_token.GSS_BUFFER_T_len;
13227c478bd9Sstevel@tonic-gate 		output_token->value = res.output_token.GSS_BUFFER_T_val;
13237c478bd9Sstevel@tonic-gate 		res.output_token.GSS_BUFFER_T_len = 0;
13247c478bd9Sstevel@tonic-gate 		res.output_token.GSS_BUFFER_T_val = NULL;
13257c478bd9Sstevel@tonic-gate 	}
13267c478bd9Sstevel@tonic-gate 
13277c478bd9Sstevel@tonic-gate 	/*
13287c478bd9Sstevel@tonic-gate 	 * free the memory allocated for the results and return with the status
13297c478bd9Sstevel@tonic-gate 	 * received in the rpc call
13307c478bd9Sstevel@tonic-gate 	 */
13317c478bd9Sstevel@tonic-gate 
13327c478bd9Sstevel@tonic-gate 	clnt_freeres(clnt, xdr_gss_delete_sec_context_res, (caddr_t)&res);
13337c478bd9Sstevel@tonic-gate 	killgssd_handle(clnt);
13347c478bd9Sstevel@tonic-gate 	return (res.status);
13357c478bd9Sstevel@tonic-gate 
13367c478bd9Sstevel@tonic-gate }
13377c478bd9Sstevel@tonic-gate 
13387c478bd9Sstevel@tonic-gate OM_uint32
13397c478bd9Sstevel@tonic-gate kgss_delete_sec_context(
13407c478bd9Sstevel@tonic-gate 		OM_uint32 *minor_status,
13417c478bd9Sstevel@tonic-gate 		gss_ctx_id_t *context_handle,
13427c478bd9Sstevel@tonic-gate 		gss_buffer_t output_token)
13437c478bd9Sstevel@tonic-gate {
13447c478bd9Sstevel@tonic-gate 	OM_uint32 err;
13457c478bd9Sstevel@tonic-gate 	struct kgss_ctx	*kctx;
13467c478bd9Sstevel@tonic-gate 
13477c478bd9Sstevel@tonic-gate 	if (*context_handle == GSS_C_NO_CONTEXT) {
13487c478bd9Sstevel@tonic-gate 		GSSLOG0(8, "kgss_delete_sec_context: Null context handle \n");
13497c478bd9Sstevel@tonic-gate 		return (GSS_S_COMPLETE);
13507c478bd9Sstevel@tonic-gate 	} else
13517c478bd9Sstevel@tonic-gate 		kctx = (struct kgss_ctx *)*context_handle;
13527c478bd9Sstevel@tonic-gate 
13537c478bd9Sstevel@tonic-gate 	if (kctx->ctx_imported == FALSE) {
1354*d4f95bf4SRichard Lowe 		if (kctx->gssd_ctx == GSSD_NO_CONTEXT) {
13557c478bd9Sstevel@tonic-gate 			KGSS_FREE(kctx);
13567c478bd9Sstevel@tonic-gate 			*context_handle = GSS_C_NO_CONTEXT;
13577c478bd9Sstevel@tonic-gate 			return (GSS_S_COMPLETE);
13587c478bd9Sstevel@tonic-gate 		}
13597c478bd9Sstevel@tonic-gate 		err = kgss_delete_sec_context_wrapped(
13607c478bd9Sstevel@tonic-gate 		    KCTX_TO_PRIVATE(*context_handle),
13617c478bd9Sstevel@tonic-gate 		    minor_status,
13627c478bd9Sstevel@tonic-gate 		    &kctx->gssd_ctx,
13637c478bd9Sstevel@tonic-gate 		    output_token,
13647c478bd9Sstevel@tonic-gate 		    kctx->gssd_ctx_verifier);
13657c478bd9Sstevel@tonic-gate 	} else {
13667c478bd9Sstevel@tonic-gate 		if (kctx->gssd_i_ctx == (gss_ctx_id_t)GSS_C_NO_CONTEXT) {
13677c478bd9Sstevel@tonic-gate 			KGSS_FREE(kctx);
13687c478bd9Sstevel@tonic-gate 			*context_handle = GSS_C_NO_CONTEXT;
13697c478bd9Sstevel@tonic-gate 			return (GSS_S_COMPLETE);
13707c478bd9Sstevel@tonic-gate 		}
13717c478bd9Sstevel@tonic-gate 		err = KGSS_DELETE_SEC_CONTEXT(minor_status, kctx,
13727c478bd9Sstevel@tonic-gate 		    &kctx->gssd_i_ctx,  output_token);
13737c478bd9Sstevel@tonic-gate 	}
13747c478bd9Sstevel@tonic-gate 	KGSS_FREE(kctx);
13757c478bd9Sstevel@tonic-gate 	*context_handle = GSS_C_NO_CONTEXT;
13767c478bd9Sstevel@tonic-gate 	return (err);
13777c478bd9Sstevel@tonic-gate 
13787c478bd9Sstevel@tonic-gate }
13797c478bd9Sstevel@tonic-gate 
13807c478bd9Sstevel@tonic-gate 
13817c478bd9Sstevel@tonic-gate OM_uint32
13827c478bd9Sstevel@tonic-gate kgss_export_sec_context_wrapped(minor_status,
13837c478bd9Sstevel@tonic-gate 				context_handle,
13847c478bd9Sstevel@tonic-gate 				output_token,
13857c478bd9Sstevel@tonic-gate 				gssd_context_verifier)
13867c478bd9Sstevel@tonic-gate 	OM_uint32 *minor_status;
13877c478bd9Sstevel@tonic-gate 	gssd_ctx_id_t *context_handle;
13887c478bd9Sstevel@tonic-gate 	gss_buffer_t output_token;
13897c478bd9Sstevel@tonic-gate 	OM_uint32 gssd_context_verifier;
13907c478bd9Sstevel@tonic-gate {
13917c478bd9Sstevel@tonic-gate 	CLIENT *clnt;
13927c478bd9Sstevel@tonic-gate 	gss_export_sec_context_arg arg;
13937c478bd9Sstevel@tonic-gate 	gss_export_sec_context_res res;
13947c478bd9Sstevel@tonic-gate 
13957c478bd9Sstevel@tonic-gate 
13967c478bd9Sstevel@tonic-gate 	/* get the client handle to GSSD */
13977c478bd9Sstevel@tonic-gate 
13987c478bd9Sstevel@tonic-gate 	if ((clnt = getgssd_handle()) == NULL) {
13997c478bd9Sstevel@tonic-gate 		GSSLOG(1, "kgss_export_sec_context_wrapped :"
14007c478bd9Sstevel@tonic-gate 			" can't connect to server on %s\n", server);
14017c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
14027c478bd9Sstevel@tonic-gate 	}
14037c478bd9Sstevel@tonic-gate 
14047c478bd9Sstevel@tonic-gate 	/* copy the procedure arguments into the rpc arg parameter */
14057c478bd9Sstevel@tonic-gate 
14067c478bd9Sstevel@tonic-gate 	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
14077c478bd9Sstevel@tonic-gate 	arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle;
14087c478bd9Sstevel@tonic-gate 	arg.gssd_context_verifier = gssd_context_verifier;
14097c478bd9Sstevel@tonic-gate 
14107c478bd9Sstevel@tonic-gate 	/* call the remote procedure */
14117c478bd9Sstevel@tonic-gate 
14127c478bd9Sstevel@tonic-gate 	(void) memset(&res, 0, sizeof (res));
14137c478bd9Sstevel@tonic-gate 	if (gss_export_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
14147c478bd9Sstevel@tonic-gate 
14157c478bd9Sstevel@tonic-gate 	/*
14167c478bd9Sstevel@tonic-gate 	 * if the RPC call times out, null out all return arguments,
14177c478bd9Sstevel@tonic-gate 	 * set minor_status to its maximum value, and return
14187c478bd9Sstevel@tonic-gate 	 * GSS_S_FAILURE
14197c478bd9Sstevel@tonic-gate 	 */
14207c478bd9Sstevel@tonic-gate 
14217c478bd9Sstevel@tonic-gate 		if (minor_status != NULL)
14227c478bd9Sstevel@tonic-gate 			*minor_status = DEFAULT_MINOR_STAT;
14237c478bd9Sstevel@tonic-gate 		if (context_handle != NULL)
14247c478bd9Sstevel@tonic-gate 			*context_handle = NULL;
14257c478bd9Sstevel@tonic-gate 		if (output_token != NULL)
14267c478bd9Sstevel@tonic-gate 			output_token->length = 0;
14277c478bd9Sstevel@tonic-gate 		killgssd_handle(clnt);
14287c478bd9Sstevel@tonic-gate 		GSSLOG0(1,
14297c478bd9Sstevel@tonic-gate 		"kgss_export_sec_context_wrapped: RPC call times out\n");
14307c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
14317c478bd9Sstevel@tonic-gate 	}
14327c478bd9Sstevel@tonic-gate 
14337c478bd9Sstevel@tonic-gate 	/* copy the rpc results into the return arguments */
14347c478bd9Sstevel@tonic-gate 
14357c478bd9Sstevel@tonic-gate 	if (minor_status != NULL)
14367c478bd9Sstevel@tonic-gate 		*minor_status = res.minor_status;
14377c478bd9Sstevel@tonic-gate 
14387c478bd9Sstevel@tonic-gate 	if (res.context_handle.GSS_CTX_ID_T_len == 0)
14397c478bd9Sstevel@tonic-gate 		*context_handle = NULL;
14407c478bd9Sstevel@tonic-gate 	else
14417c478bd9Sstevel@tonic-gate 		*context_handle =
14427c478bd9Sstevel@tonic-gate 		    *((gssd_ctx_id_t *)res.context_handle.GSS_CTX_ID_T_val);
14437c478bd9Sstevel@tonic-gate 
14447c478bd9Sstevel@tonic-gate 	if (output_token != NULL) {
14457c478bd9Sstevel@tonic-gate 		output_token->length = res.output_token.GSS_BUFFER_T_len;
14467c478bd9Sstevel@tonic-gate 		output_token->value =
14477c478bd9Sstevel@tonic-gate 			(void *)  MALLOC(output_token->length);
14487c478bd9Sstevel@tonic-gate 		(void) memcpy(output_token->value,
14497c478bd9Sstevel@tonic-gate 			res.output_token.GSS_BUFFER_T_val,
14507c478bd9Sstevel@tonic-gate 			output_token->length);
14517c478bd9Sstevel@tonic-gate 	}
14527c478bd9Sstevel@tonic-gate 
14537c478bd9Sstevel@tonic-gate 	/*
14547c478bd9Sstevel@tonic-gate 	 * free the memory allocated for the results and return with the status
14557c478bd9Sstevel@tonic-gate 	 * received in the rpc call
14567c478bd9Sstevel@tonic-gate 	 */
14577c478bd9Sstevel@tonic-gate 
14587c478bd9Sstevel@tonic-gate 	clnt_freeres(clnt, xdr_gss_export_sec_context_res, (caddr_t)&res);
14597c478bd9Sstevel@tonic-gate 	killgssd_handle(clnt);
14607c478bd9Sstevel@tonic-gate 	return (res.status);
14617c478bd9Sstevel@tonic-gate 
14627c478bd9Sstevel@tonic-gate }
14637c478bd9Sstevel@tonic-gate 
14647c478bd9Sstevel@tonic-gate OM_uint32
14657c478bd9Sstevel@tonic-gate kgss_export_sec_context(minor_status,
14667c478bd9Sstevel@tonic-gate 			context_handle,
14677c478bd9Sstevel@tonic-gate 			output_token)
14687c478bd9Sstevel@tonic-gate 	OM_uint32 *minor_status;
14697c478bd9Sstevel@tonic-gate 	gss_ctx_id_t context_handle;
14707c478bd9Sstevel@tonic-gate 	gss_buffer_t output_token;
14717c478bd9Sstevel@tonic-gate {
14727c478bd9Sstevel@tonic-gate 	struct kgss_ctx	*kctx;
14737c478bd9Sstevel@tonic-gate 
14747c478bd9Sstevel@tonic-gate 	if (context_handle == GSS_C_NO_CONTEXT)
14757c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
14767c478bd9Sstevel@tonic-gate 	else
14777c478bd9Sstevel@tonic-gate 		kctx = (struct kgss_ctx *)context_handle;
14787c478bd9Sstevel@tonic-gate 
14797c478bd9Sstevel@tonic-gate 
14807c478bd9Sstevel@tonic-gate 
14817c478bd9Sstevel@tonic-gate 	/*
14827c478bd9Sstevel@tonic-gate 	 *  If there is a kernel module then import_sec context must be
14837c478bd9Sstevel@tonic-gate 	 *  supported and we make an upcall to export_sec_context.
14847c478bd9Sstevel@tonic-gate 	 *  If there is no kernel module then we return an error
14857c478bd9Sstevel@tonic-gate 	 */
14867c478bd9Sstevel@tonic-gate 
14877c478bd9Sstevel@tonic-gate 	*minor_status = 0;
14887c478bd9Sstevel@tonic-gate 
14897c478bd9Sstevel@tonic-gate 	if (kctx->mech->gss_import_sec_context) {
14907c478bd9Sstevel@tonic-gate 		GSSLOG0(8, "kgss_export_sec_context: Kernel mod available \n");
14917c478bd9Sstevel@tonic-gate 		return (kgss_export_sec_context_wrapped(minor_status,
14927c478bd9Sstevel@tonic-gate 						&kctx->gssd_ctx,
14937c478bd9Sstevel@tonic-gate 						output_token,
14947c478bd9Sstevel@tonic-gate 						kctx->gssd_ctx_verifier));
14957c478bd9Sstevel@tonic-gate 
14967c478bd9Sstevel@tonic-gate 	} else {
14977c478bd9Sstevel@tonic-gate 
14987c478bd9Sstevel@tonic-gate 		/*
14997c478bd9Sstevel@tonic-gate 		 * This is not the right error value; instead of
15007c478bd9Sstevel@tonic-gate 		 * inventing  new error we return GSS_S_NAME_NOT_MN
15017c478bd9Sstevel@tonic-gate 		 * This error is not returned by the export routine
15027c478bd9Sstevel@tonic-gate 		 */
15037c478bd9Sstevel@tonic-gate 
15047c478bd9Sstevel@tonic-gate 		GSSLOG0(8, "kgss_export_sec_context: Kernel mod "
15057c478bd9Sstevel@tonic-gate 			"unavailable \n");
15067c478bd9Sstevel@tonic-gate 		return (GSS_S_NAME_NOT_MN);
15077c478bd9Sstevel@tonic-gate 	}
15087c478bd9Sstevel@tonic-gate 
15097c478bd9Sstevel@tonic-gate }
15107c478bd9Sstevel@tonic-gate 
15117c478bd9Sstevel@tonic-gate OM_uint32
15127c478bd9Sstevel@tonic-gate kgss_import_sec_context(minor_status,
15137c478bd9Sstevel@tonic-gate 			interprocess_token,
15147c478bd9Sstevel@tonic-gate 			context_handle)
15157c478bd9Sstevel@tonic-gate 
15167c478bd9Sstevel@tonic-gate OM_uint32 *		minor_status;
15177c478bd9Sstevel@tonic-gate const gss_buffer_t	interprocess_token;
15187c478bd9Sstevel@tonic-gate gss_ctx_id_t 		context_handle;
15197c478bd9Sstevel@tonic-gate 
15207c478bd9Sstevel@tonic-gate {
15217c478bd9Sstevel@tonic-gate OM_uint32 status;
15227c478bd9Sstevel@tonic-gate struct kgss_ctx	*kctx;
15237c478bd9Sstevel@tonic-gate 
15247c478bd9Sstevel@tonic-gate size_t		length;
15257c478bd9Sstevel@tonic-gate char		*p;
15267c478bd9Sstevel@tonic-gate gss_buffer_desc token;
15277c478bd9Sstevel@tonic-gate gss_ctx_id_t	internal_ctx_id;
15287c478bd9Sstevel@tonic-gate 	kctx = (struct kgss_ctx *)context_handle;
15297c478bd9Sstevel@tonic-gate 
1530*d4f95bf4SRichard Lowe 	if (kctx->gssd_ctx != GSSD_NO_CONTEXT) {
15317c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
15327c478bd9Sstevel@tonic-gate 	}
15337c478bd9Sstevel@tonic-gate 
15347c478bd9Sstevel@tonic-gate 	if (!(KCTX_TO_MECH(context_handle)->gss_import_sec_context)) {
15357c478bd9Sstevel@tonic-gate 
15367c478bd9Sstevel@tonic-gate 	/*
15377c478bd9Sstevel@tonic-gate 	 *  This should never happen
15387c478bd9Sstevel@tonic-gate 	 *  If Kernel import sec context does not exist the export
15397c478bd9Sstevel@tonic-gate 	 *  sec context should have caught this and returned an error
15407c478bd9Sstevel@tonic-gate 	 *  and the caller should not have called this routine
15417c478bd9Sstevel@tonic-gate 	 */
15427c478bd9Sstevel@tonic-gate 		GSSLOG0(1, "import_sec_context  called improperly\n");
15437c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
15447c478bd9Sstevel@tonic-gate 	}
15457c478bd9Sstevel@tonic-gate 	*minor_status = 0;
15467c478bd9Sstevel@tonic-gate 
15477c478bd9Sstevel@tonic-gate 	if (interprocess_token->length == 0 || interprocess_token->value == 0)
15487c478bd9Sstevel@tonic-gate 		return (GSS_S_DEFECTIVE_TOKEN);
15497c478bd9Sstevel@tonic-gate 
15507c478bd9Sstevel@tonic-gate 	status = GSS_S_FAILURE;
15517c478bd9Sstevel@tonic-gate 
15527c478bd9Sstevel@tonic-gate 	p = interprocess_token->value;
15537c478bd9Sstevel@tonic-gate 	length = *p++;
15547c478bd9Sstevel@tonic-gate 	length = (length << 8) + *p++;
15557c478bd9Sstevel@tonic-gate 	length = (length << 8) + *p++;
15567c478bd9Sstevel@tonic-gate 	length = (length << 8) + *p++;
15577c478bd9Sstevel@tonic-gate 
15587c478bd9Sstevel@tonic-gate 	p += length;
15597c478bd9Sstevel@tonic-gate 
15607c478bd9Sstevel@tonic-gate 	token.length = interprocess_token->length - 4 - length;
15617c478bd9Sstevel@tonic-gate 	token.value = p;
15627c478bd9Sstevel@tonic-gate 
15637c478bd9Sstevel@tonic-gate 	/*
15647c478bd9Sstevel@tonic-gate 	 * select the approprate underlying mechanism routine and
15657c478bd9Sstevel@tonic-gate 	 * call it.
15667c478bd9Sstevel@tonic-gate 	 */
15677c478bd9Sstevel@tonic-gate 
15687c478bd9Sstevel@tonic-gate 	status = KGSS_IMPORT_SEC_CONTEXT(minor_status, &token, kctx,
15697c478bd9Sstevel@tonic-gate 				&internal_ctx_id);
15707c478bd9Sstevel@tonic-gate 
15717c478bd9Sstevel@tonic-gate 	if (status == GSS_S_COMPLETE) {
15727c478bd9Sstevel@tonic-gate 		KCTX_TO_I_CTX(kctx) = internal_ctx_id;
15737c478bd9Sstevel@tonic-gate 		kctx->ctx_imported = TRUE;
15747c478bd9Sstevel@tonic-gate 		return (GSS_S_COMPLETE);
15757c478bd9Sstevel@tonic-gate 	} else
15767c478bd9Sstevel@tonic-gate 		return (status);
15777c478bd9Sstevel@tonic-gate }
15787c478bd9Sstevel@tonic-gate 
15797c478bd9Sstevel@tonic-gate /*ARGSUSED*/
15807c478bd9Sstevel@tonic-gate OM_uint32
15817c478bd9Sstevel@tonic-gate kgss_context_time(minor_status,
15827c478bd9Sstevel@tonic-gate 		context_handle,
15837c478bd9Sstevel@tonic-gate 		time_rec,
15847c478bd9Sstevel@tonic-gate 		uid)
15857c478bd9Sstevel@tonic-gate 	OM_uint32 *minor_status;
15867c478bd9Sstevel@tonic-gate 	const gss_ctx_id_t context_handle;
15877c478bd9Sstevel@tonic-gate 	OM_uint32 *time_rec;
15887c478bd9Sstevel@tonic-gate 	uid_t uid;
15897c478bd9Sstevel@tonic-gate {
15907c478bd9Sstevel@tonic-gate 	return (GSS_S_FAILURE);
15917c478bd9Sstevel@tonic-gate }
15927c478bd9Sstevel@tonic-gate 
15937c478bd9Sstevel@tonic-gate /*ARGSUSED*/
15947c478bd9Sstevel@tonic-gate static OM_uint32
15957c478bd9Sstevel@tonic-gate kgss_sign_wrapped(void *private,
15967c478bd9Sstevel@tonic-gate 	OM_uint32 *minor_status,
15977c478bd9Sstevel@tonic-gate 	const gss_ctx_id_t ctx_handle,
15987c478bd9Sstevel@tonic-gate 	int qop_req,
15997c478bd9Sstevel@tonic-gate 	const gss_buffer_t message_buffer,
16007c478bd9Sstevel@tonic-gate 	gss_buffer_t msg_token,
16017c478bd9Sstevel@tonic-gate 	OM_uint32 gssd_context_verifier)
16027c478bd9Sstevel@tonic-gate {
16037c478bd9Sstevel@tonic-gate 	CLIENT *clnt;
16047c478bd9Sstevel@tonic-gate 	gssd_ctx_id_t context_handle;
16057c478bd9Sstevel@tonic-gate 
16067c478bd9Sstevel@tonic-gate 	gss_sign_arg arg;
16077c478bd9Sstevel@tonic-gate 	gss_sign_res res;
16087c478bd9Sstevel@tonic-gate 	context_handle = (gssd_ctx_id_t)KCTX_TO_GSSD_CTX(ctx_handle);
16097c478bd9Sstevel@tonic-gate 	/* get the client handle to GSSD */
16107c478bd9Sstevel@tonic-gate 
16117c478bd9Sstevel@tonic-gate 	if ((clnt = getgssd_handle()) == NULL) {
16127c478bd9Sstevel@tonic-gate 		GSSLOG(1, "kgss_sign: can't connect to server on %s\n", server);
16137c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
16147c478bd9Sstevel@tonic-gate 	}
16157c478bd9Sstevel@tonic-gate 
16167c478bd9Sstevel@tonic-gate 	/* copy the procedure arguments into the rpc arg parameter */
16177c478bd9Sstevel@tonic-gate 
16187c478bd9Sstevel@tonic-gate 	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
16197c478bd9Sstevel@tonic-gate 	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
16207c478bd9Sstevel@tonic-gate 
16217c478bd9Sstevel@tonic-gate 	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
16227c478bd9Sstevel@tonic-gate 	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
16237c478bd9Sstevel@tonic-gate 	arg.gssd_context_verifier = gssd_context_verifier;
16247c478bd9Sstevel@tonic-gate 
16257c478bd9Sstevel@tonic-gate 	arg.qop_req = qop_req;
16267c478bd9Sstevel@tonic-gate 
16277c478bd9Sstevel@tonic-gate 	arg.message_buffer.GSS_BUFFER_T_len = (uint_t)message_buffer->length;
16287c478bd9Sstevel@tonic-gate 	arg.message_buffer.GSS_BUFFER_T_val = (char *)message_buffer->value;
16297c478bd9Sstevel@tonic-gate 
16307c478bd9Sstevel@tonic-gate 	/* call the remote procedure */
16317c478bd9Sstevel@tonic-gate 
16327c478bd9Sstevel@tonic-gate 	bzero((caddr_t)&res, sizeof (res));
16337c478bd9Sstevel@tonic-gate 	if (gss_sign_1(&arg, &res, clnt) != RPC_SUCCESS) {
16347c478bd9Sstevel@tonic-gate 
16357c478bd9Sstevel@tonic-gate 	/*
16367c478bd9Sstevel@tonic-gate 	 * if the RPC call times out, null out all return arguments, set
16377c478bd9Sstevel@tonic-gate 	 * minor_status to its maximum value, and return GSS_S_FAILURE
16387c478bd9Sstevel@tonic-gate 	 */
16397c478bd9Sstevel@tonic-gate 
16407c478bd9Sstevel@tonic-gate 		if (minor_status != NULL)
16417c478bd9Sstevel@tonic-gate 			*minor_status = DEFAULT_MINOR_STAT;
16427c478bd9Sstevel@tonic-gate 		if (msg_token != NULL)
16437c478bd9Sstevel@tonic-gate 			msg_token->length = 0;
16447c478bd9Sstevel@tonic-gate 
16457c478bd9Sstevel@tonic-gate 		killgssd_handle(clnt);
16467c478bd9Sstevel@tonic-gate 		GSSLOG0(1, "kgss_sign: RPC call times out\n");
16477c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
16487c478bd9Sstevel@tonic-gate 	}
16497c478bd9Sstevel@tonic-gate 
16507c478bd9Sstevel@tonic-gate 	/* copy the rpc results into the return arguments */
16517c478bd9Sstevel@tonic-gate 
16527c478bd9Sstevel@tonic-gate 	if (minor_status != NULL)
16537c478bd9Sstevel@tonic-gate 		*minor_status = res.minor_status;
16547c478bd9Sstevel@tonic-gate 
16557c478bd9Sstevel@tonic-gate 	if (msg_token != NULL) {
16567c478bd9Sstevel@tonic-gate 		msg_token->length = res.msg_token.GSS_BUFFER_T_len;
16577c478bd9Sstevel@tonic-gate 		msg_token->value = (void *) MALLOC(msg_token->length);
16587c478bd9Sstevel@tonic-gate 		(void) memcpy(msg_token->value, res.msg_token.GSS_BUFFER_T_val,
16597c478bd9Sstevel@tonic-gate 		    msg_token->length);
16607c478bd9Sstevel@tonic-gate 	}
16617c478bd9Sstevel@tonic-gate 
16627c478bd9Sstevel@tonic-gate 	/*
16637c478bd9Sstevel@tonic-gate 	 * free the memory allocated for the results and return with the status
16647c478bd9Sstevel@tonic-gate 	 * received in the rpc call
16657c478bd9Sstevel@tonic-gate 	 */
16667c478bd9Sstevel@tonic-gate 
16677c478bd9Sstevel@tonic-gate 	clnt_freeres(clnt, xdr_gss_sign_res, (caddr_t)&res);
16687c478bd9Sstevel@tonic-gate 	killgssd_handle(clnt);
16697c478bd9Sstevel@tonic-gate 	return (res.status);
16707c478bd9Sstevel@tonic-gate 
16717c478bd9Sstevel@tonic-gate }
16727c478bd9Sstevel@tonic-gate 
16737c478bd9Sstevel@tonic-gate OM_uint32
16747c478bd9Sstevel@tonic-gate kgss_sign(
16757c478bd9Sstevel@tonic-gate 	OM_uint32 *minor_status,
16767c478bd9Sstevel@tonic-gate 	const gss_ctx_id_t context_handle,
16777c478bd9Sstevel@tonic-gate 	int qop_req,
16787c478bd9Sstevel@tonic-gate 	const gss_buffer_t message_buffer,
16797c478bd9Sstevel@tonic-gate 	gss_buffer_t msg_token)
16807c478bd9Sstevel@tonic-gate {
16817c478bd9Sstevel@tonic-gate 	if (context_handle == GSS_C_NO_CONTEXT)
16827c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
16837c478bd9Sstevel@tonic-gate 	return (KGSS_SIGN(minor_status, context_handle, qop_req,
16847c478bd9Sstevel@tonic-gate 	    message_buffer, msg_token));
16857c478bd9Sstevel@tonic-gate }
16867c478bd9Sstevel@tonic-gate 
16877c478bd9Sstevel@tonic-gate /*ARGSUSED*/
16887c478bd9Sstevel@tonic-gate static OM_uint32
16897c478bd9Sstevel@tonic-gate kgss_verify_wrapped(void *private,
16907c478bd9Sstevel@tonic-gate 	OM_uint32 *minor_status,
16917c478bd9Sstevel@tonic-gate 	const gss_ctx_id_t ctx_handle,
16927c478bd9Sstevel@tonic-gate 	const gss_buffer_t message_buffer,
16937c478bd9Sstevel@tonic-gate 	const gss_buffer_t token_buffer,
16947c478bd9Sstevel@tonic-gate 	int *qop_state,
16957c478bd9Sstevel@tonic-gate 	OM_uint32 gssd_context_verifier)
16967c478bd9Sstevel@tonic-gate {
16977c478bd9Sstevel@tonic-gate 	CLIENT *clnt;
16987c478bd9Sstevel@tonic-gate 
16997c478bd9Sstevel@tonic-gate 	gssd_ctx_id_t context_handle;
17007c478bd9Sstevel@tonic-gate 	gss_verify_arg arg;
17017c478bd9Sstevel@tonic-gate 	gss_verify_res res;
17027c478bd9Sstevel@tonic-gate 
17037c478bd9Sstevel@tonic-gate 	context_handle = (gssd_ctx_id_t)KCTX_TO_GSSD_CTX(ctx_handle);
17047c478bd9Sstevel@tonic-gate 
17057c478bd9Sstevel@tonic-gate 	/* get the client handle to GSSD */
17067c478bd9Sstevel@tonic-gate 
17077c478bd9Sstevel@tonic-gate 	if ((clnt = getgssd_handle()) == NULL) {
17087c478bd9Sstevel@tonic-gate 		GSSLOG(1, "kgss_verify: can't connect to server on %s\n",
17097c478bd9Sstevel@tonic-gate 		    server);
17107c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
17117c478bd9Sstevel@tonic-gate 	}
17127c478bd9Sstevel@tonic-gate 
17137c478bd9Sstevel@tonic-gate 	/* copy the procedure arguments into the rpc arg parameter */
17147c478bd9Sstevel@tonic-gate 
17157c478bd9Sstevel@tonic-gate 	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gss_ctx_id_t);
17167c478bd9Sstevel@tonic-gate 	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
17177c478bd9Sstevel@tonic-gate 
17187c478bd9Sstevel@tonic-gate 	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
17197c478bd9Sstevel@tonic-gate 	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
17207c478bd9Sstevel@tonic-gate 	arg.gssd_context_verifier = gssd_context_verifier;
17217c478bd9Sstevel@tonic-gate 
17227c478bd9Sstevel@tonic-gate 	arg.message_buffer.GSS_BUFFER_T_len = (uint_t)message_buffer->length;
17237c478bd9Sstevel@tonic-gate 	arg.message_buffer.GSS_BUFFER_T_val = (char *)message_buffer->value;
17247c478bd9Sstevel@tonic-gate 
17257c478bd9Sstevel@tonic-gate 	arg.token_buffer.GSS_BUFFER_T_len = (uint_t)token_buffer->length;
17267c478bd9Sstevel@tonic-gate 	arg.token_buffer.GSS_BUFFER_T_val = (char *)token_buffer->value;
17277c478bd9Sstevel@tonic-gate 
17287c478bd9Sstevel@tonic-gate 	/* call the remote procedure */
17297c478bd9Sstevel@tonic-gate 
17307c478bd9Sstevel@tonic-gate 	bzero((caddr_t)&res, sizeof (res));
17317c478bd9Sstevel@tonic-gate 	if (gss_verify_1(&arg, &res, clnt) != RPC_SUCCESS) {
17327c478bd9Sstevel@tonic-gate 
17337c478bd9Sstevel@tonic-gate 	/*
17347c478bd9Sstevel@tonic-gate 	 * if the RPC call times out, null out all return arguments, set
17357c478bd9Sstevel@tonic-gate 	 * minor_status to its maximum value, and return GSS_S_FAILURE
17367c478bd9Sstevel@tonic-gate 	 */
17377c478bd9Sstevel@tonic-gate 
17387c478bd9Sstevel@tonic-gate 		if (minor_status != NULL)
17397c478bd9Sstevel@tonic-gate 			*minor_status = DEFAULT_MINOR_STAT;
17407c478bd9Sstevel@tonic-gate 		if (qop_state != NULL)
17417c478bd9Sstevel@tonic-gate 			*qop_state = 0;
17427c478bd9Sstevel@tonic-gate 
17437c478bd9Sstevel@tonic-gate 		killgssd_handle(clnt);
17447c478bd9Sstevel@tonic-gate 		GSSLOG0(1, "kgss_verify: RPC call times out\n");
17457c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
17467c478bd9Sstevel@tonic-gate 	}
17477c478bd9Sstevel@tonic-gate 
17487c478bd9Sstevel@tonic-gate 	/* copy the rpc results into the return arguments */
17497c478bd9Sstevel@tonic-gate 
17507c478bd9Sstevel@tonic-gate 	if (minor_status != NULL)
17517c478bd9Sstevel@tonic-gate 		*minor_status = res.minor_status;
17527c478bd9Sstevel@tonic-gate 
17537c478bd9Sstevel@tonic-gate 	if (qop_state != NULL)
17547c478bd9Sstevel@tonic-gate 		*qop_state = res.qop_state;
17557c478bd9Sstevel@tonic-gate 
17567c478bd9Sstevel@tonic-gate 	/* return with status returned in rpc call */
17577c478bd9Sstevel@tonic-gate 
17587c478bd9Sstevel@tonic-gate 	killgssd_handle(clnt);
17597c478bd9Sstevel@tonic-gate 	return (res.status);
17607c478bd9Sstevel@tonic-gate 
17617c478bd9Sstevel@tonic-gate }
17627c478bd9Sstevel@tonic-gate 
17637c478bd9Sstevel@tonic-gate OM_uint32
17647c478bd9Sstevel@tonic-gate kgss_verify(OM_uint32 *minor_status,
17657c478bd9Sstevel@tonic-gate 		const gss_ctx_id_t context_handle,
17667c478bd9Sstevel@tonic-gate 		const gss_buffer_t message_buffer,
17677c478bd9Sstevel@tonic-gate 		const gss_buffer_t token_buffer,
17687c478bd9Sstevel@tonic-gate 		int *qop_state)
17697c478bd9Sstevel@tonic-gate {
17707c478bd9Sstevel@tonic-gate 	if (context_handle == GSS_C_NO_CONTEXT)
17717c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
17727c478bd9Sstevel@tonic-gate 	return (KGSS_VERIFY(minor_status, context_handle,
1773*d4f95bf4SRichard Lowe 	    message_buffer, token_buffer, qop_state));
17747c478bd9Sstevel@tonic-gate }
17757c478bd9Sstevel@tonic-gate 
17767c478bd9Sstevel@tonic-gate /*ARGSUSED*/
17777c478bd9Sstevel@tonic-gate static OM_uint32
17787c478bd9Sstevel@tonic-gate kgss_seal_wrapped(void *private,
17797c478bd9Sstevel@tonic-gate 	OM_uint32 *minor_status,
17807c478bd9Sstevel@tonic-gate 	const gss_ctx_id_t ctx_handle,
17817c478bd9Sstevel@tonic-gate 	int conf_req_flag,
17827c478bd9Sstevel@tonic-gate 	int qop_req,
17837c478bd9Sstevel@tonic-gate 	const gss_buffer_t input_message_buffer,
17847c478bd9Sstevel@tonic-gate 	int *conf_state,
17857c478bd9Sstevel@tonic-gate 	gss_buffer_t output_message_buffer,
17867c478bd9Sstevel@tonic-gate 	OM_uint32 gssd_context_verifier)
17877c478bd9Sstevel@tonic-gate {
17887c478bd9Sstevel@tonic-gate 	CLIENT *clnt;
17897c478bd9Sstevel@tonic-gate 	gssd_ctx_id_t	context_handle;
17907c478bd9Sstevel@tonic-gate 
17917c478bd9Sstevel@tonic-gate 	gss_seal_arg arg;
17927c478bd9Sstevel@tonic-gate 	gss_seal_res res;
17937c478bd9Sstevel@tonic-gate 
17947c478bd9Sstevel@tonic-gate 	context_handle = (gssd_ctx_id_t)KCTX_TO_GSSD_CTX(ctx_handle);
17957c478bd9Sstevel@tonic-gate 
17967c478bd9Sstevel@tonic-gate 	/* get the client handle to GSSD */
17977c478bd9Sstevel@tonic-gate 
17987c478bd9Sstevel@tonic-gate 	if ((clnt = getgssd_handle()) == NULL) {
17997c478bd9Sstevel@tonic-gate 		GSSLOG(1, "kgss_seal: can't connect to server on %s\n", server);
18007c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
18017c478bd9Sstevel@tonic-gate 	}
18027c478bd9Sstevel@tonic-gate 
18037c478bd9Sstevel@tonic-gate 	/* copy the procedure arguments into the rpc arg parameter */
18047c478bd9Sstevel@tonic-gate 
18057c478bd9Sstevel@tonic-gate 	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gss_ctx_id_t);
18067c478bd9Sstevel@tonic-gate 	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
18077c478bd9Sstevel@tonic-gate 
18087c478bd9Sstevel@tonic-gate 	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (OM_uint32);
18097c478bd9Sstevel@tonic-gate 	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
18107c478bd9Sstevel@tonic-gate 	arg.gssd_context_verifier = gssd_context_verifier;
18117c478bd9Sstevel@tonic-gate 
18127c478bd9Sstevel@tonic-gate 	arg.conf_req_flag = conf_req_flag;
18137c478bd9Sstevel@tonic-gate 
18147c478bd9Sstevel@tonic-gate 	arg.qop_req = qop_req;
18157c478bd9Sstevel@tonic-gate 
18167c478bd9Sstevel@tonic-gate 	arg.input_message_buffer.GSS_BUFFER_T_len =
18177c478bd9Sstevel@tonic-gate 	    (uint_t)input_message_buffer->length;
18187c478bd9Sstevel@tonic-gate 
18197c478bd9Sstevel@tonic-gate 	arg.input_message_buffer.GSS_BUFFER_T_val =
18207c478bd9Sstevel@tonic-gate 	    (char *)input_message_buffer->value;
18217c478bd9Sstevel@tonic-gate 
18227c478bd9Sstevel@tonic-gate 	/* call the remote procedure */
18237c478bd9Sstevel@tonic-gate 
18247c478bd9Sstevel@tonic-gate 	bzero((caddr_t)&res, sizeof (res));
18257c478bd9Sstevel@tonic-gate 	if (gss_seal_1(&arg, &res, clnt) != RPC_SUCCESS) {
18267c478bd9Sstevel@tonic-gate 
18277c478bd9Sstevel@tonic-gate 	/*
18287c478bd9Sstevel@tonic-gate 	 * if the RPC call times out, null out all return arguments, set
18297c478bd9Sstevel@tonic-gate 	 * minor_status to its maximum value, and return GSS_S_FAILURE
18307c478bd9Sstevel@tonic-gate 	 */
18317c478bd9Sstevel@tonic-gate 
18327c478bd9Sstevel@tonic-gate 		if (minor_status != NULL)
18337c478bd9Sstevel@tonic-gate 			*minor_status = DEFAULT_MINOR_STAT;
18347c478bd9Sstevel@tonic-gate 		if (conf_state != NULL)
18357c478bd9Sstevel@tonic-gate 			*conf_state = 0;
18367c478bd9Sstevel@tonic-gate 		if (output_message_buffer != NULL)
18377c478bd9Sstevel@tonic-gate 			output_message_buffer->length = 0;
18387c478bd9Sstevel@tonic-gate 
18397c478bd9Sstevel@tonic-gate 		killgssd_handle(clnt);
18407c478bd9Sstevel@tonic-gate 		GSSLOG0(1, "kgss_seal: RPC call times out\n");
18417c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
18427c478bd9Sstevel@tonic-gate 	}
18437c478bd9Sstevel@tonic-gate 
18447c478bd9Sstevel@tonic-gate 	/* copy the rpc results into the return arguments */
18457c478bd9Sstevel@tonic-gate 
18467c478bd9Sstevel@tonic-gate 	if (minor_status != NULL)
18477c478bd9Sstevel@tonic-gate 		*minor_status = res.minor_status;
18487c478bd9Sstevel@tonic-gate 
18497c478bd9Sstevel@tonic-gate 	if (conf_state != NULL)
18507c478bd9Sstevel@tonic-gate 		*conf_state = res.conf_state;
18517c478bd9Sstevel@tonic-gate 
18527c478bd9Sstevel@tonic-gate 	if (output_message_buffer != NULL) {
18537c478bd9Sstevel@tonic-gate 		output_message_buffer->length =
18547c478bd9Sstevel@tonic-gate 		    res.output_message_buffer.GSS_BUFFER_T_len;
18557c478bd9Sstevel@tonic-gate 
18567c478bd9Sstevel@tonic-gate 		output_message_buffer->value =
18577c478bd9Sstevel@tonic-gate 		    (void *) MALLOC(output_message_buffer->length);
18587c478bd9Sstevel@tonic-gate 		(void) memcpy(output_message_buffer->value,
18597c478bd9Sstevel@tonic-gate 		    res.output_message_buffer.GSS_BUFFER_T_val,
18607c478bd9Sstevel@tonic-gate 		    output_message_buffer->length);
18617c478bd9Sstevel@tonic-gate 	}
18627c478bd9Sstevel@tonic-gate 
18637c478bd9Sstevel@tonic-gate 	/*
18647c478bd9Sstevel@tonic-gate 	 * free the memory allocated for the results and return with the status
18657c478bd9Sstevel@tonic-gate 	 * received in the rpc call
18667c478bd9Sstevel@tonic-gate 	 */
18677c478bd9Sstevel@tonic-gate 
18687c478bd9Sstevel@tonic-gate 	clnt_freeres(clnt, xdr_gss_seal_res, (caddr_t)&res);
18697c478bd9Sstevel@tonic-gate 	killgssd_handle(clnt);
18707c478bd9Sstevel@tonic-gate 	return (res.status);
18717c478bd9Sstevel@tonic-gate }
18727c478bd9Sstevel@tonic-gate 
18737c478bd9Sstevel@tonic-gate /*ARGSUSED*/
18747c478bd9Sstevel@tonic-gate OM_uint32
18757c478bd9Sstevel@tonic-gate kgss_seal(OM_uint32 *minor_status,
18767c478bd9Sstevel@tonic-gate 	const gss_ctx_id_t context_handle,
18777c478bd9Sstevel@tonic-gate 	int conf_req_flag,
18787c478bd9Sstevel@tonic-gate 	int qop_req,
18797c478bd9Sstevel@tonic-gate 	const gss_buffer_t input_message_buffer,
18807c478bd9Sstevel@tonic-gate 	int *conf_state,
18817c478bd9Sstevel@tonic-gate 	gss_buffer_t output_message_buffer)
18827c478bd9Sstevel@tonic-gate 
18837c478bd9Sstevel@tonic-gate {
18847c478bd9Sstevel@tonic-gate 	if (context_handle == GSS_C_NO_CONTEXT)
18857c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
18867c478bd9Sstevel@tonic-gate 	return (KGSS_SEAL(minor_status, context_handle,
18877c478bd9Sstevel@tonic-gate 		conf_req_flag, qop_req,
18887c478bd9Sstevel@tonic-gate 		input_message_buffer, conf_state,
18897c478bd9Sstevel@tonic-gate 		output_message_buffer));
18907c478bd9Sstevel@tonic-gate }
18917c478bd9Sstevel@tonic-gate 
18927c478bd9Sstevel@tonic-gate /*ARGSUSED*/
18937c478bd9Sstevel@tonic-gate static OM_uint32
18947c478bd9Sstevel@tonic-gate kgss_unseal_wrapped(void *private,
18957c478bd9Sstevel@tonic-gate 	OM_uint32 *minor_status,
18967c478bd9Sstevel@tonic-gate 	const gss_ctx_id_t ctx_handle,
18977c478bd9Sstevel@tonic-gate 	const gss_buffer_t input_message_buffer,
18987c478bd9Sstevel@tonic-gate 	gss_buffer_t output_message_buffer,
18997c478bd9Sstevel@tonic-gate 	int *conf_state,
19007c478bd9Sstevel@tonic-gate 	int *qop_state,
19017c478bd9Sstevel@tonic-gate 	OM_uint32 gssd_context_verifier)
19027c478bd9Sstevel@tonic-gate {
19037c478bd9Sstevel@tonic-gate 	CLIENT *clnt;
19047c478bd9Sstevel@tonic-gate 
19057c478bd9Sstevel@tonic-gate 	gss_unseal_arg arg;
19067c478bd9Sstevel@tonic-gate 	gss_unseal_res res;
19077c478bd9Sstevel@tonic-gate 	gssd_ctx_id_t context_handle;
19087c478bd9Sstevel@tonic-gate 
19097c478bd9Sstevel@tonic-gate 	context_handle = (gssd_ctx_id_t)KCTX_TO_GSSD_CTX(ctx_handle);
19107c478bd9Sstevel@tonic-gate 
19117c478bd9Sstevel@tonic-gate 	/* get the client handle to GSSD */
19127c478bd9Sstevel@tonic-gate 
19137c478bd9Sstevel@tonic-gate 	if ((clnt = getgssd_handle()) == NULL) {
19147c478bd9Sstevel@tonic-gate 		GSSLOG(1, "kgss_unseal: can't connect to server on %s\n",
19157c478bd9Sstevel@tonic-gate 		    server);
19167c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
19177c478bd9Sstevel@tonic-gate 	}
19187c478bd9Sstevel@tonic-gate 
19197c478bd9Sstevel@tonic-gate 	/* copy the procedure arguments into the rpc arg parameter */
19207c478bd9Sstevel@tonic-gate 
19217c478bd9Sstevel@tonic-gate 	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gss_ctx_id_t);
19227c478bd9Sstevel@tonic-gate 	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
19237c478bd9Sstevel@tonic-gate 
19247c478bd9Sstevel@tonic-gate 	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
19257c478bd9Sstevel@tonic-gate 	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
19267c478bd9Sstevel@tonic-gate 	arg.gssd_context_verifier = gssd_context_verifier;
19277c478bd9Sstevel@tonic-gate 
19287c478bd9Sstevel@tonic-gate 	arg.input_message_buffer.GSS_BUFFER_T_len =
19297c478bd9Sstevel@tonic-gate 	    (uint_t)input_message_buffer->length;
19307c478bd9Sstevel@tonic-gate 
19317c478bd9Sstevel@tonic-gate 	arg.input_message_buffer.GSS_BUFFER_T_val =
19327c478bd9Sstevel@tonic-gate 	    (char *)input_message_buffer->value;
19337c478bd9Sstevel@tonic-gate 
19347c478bd9Sstevel@tonic-gate 	/* call the remote procedure */
19357c478bd9Sstevel@tonic-gate 
19367c478bd9Sstevel@tonic-gate 	bzero((caddr_t)&res, sizeof (res));
19377c478bd9Sstevel@tonic-gate 	if (gss_unseal_1(&arg, &res, clnt) != RPC_SUCCESS) {
19387c478bd9Sstevel@tonic-gate 
19397c478bd9Sstevel@tonic-gate 	/*
19407c478bd9Sstevel@tonic-gate 	 * if the RPC call times out, null out all return arguments, set
19417c478bd9Sstevel@tonic-gate 	 * minor_status to its maximum value, and return GSS_S_FAILURE
19427c478bd9Sstevel@tonic-gate 	 */
19437c478bd9Sstevel@tonic-gate 
19447c478bd9Sstevel@tonic-gate 		if (minor_status != NULL)
19457c478bd9Sstevel@tonic-gate 			*minor_status = DEFAULT_MINOR_STAT;
19467c478bd9Sstevel@tonic-gate 		if (output_message_buffer != NULL)
19477c478bd9Sstevel@tonic-gate 			output_message_buffer->length = 0;
19487c478bd9Sstevel@tonic-gate 		if (conf_state != NULL)
19497c478bd9Sstevel@tonic-gate 			*conf_state = 0;
19507c478bd9Sstevel@tonic-gate 		if (qop_state != NULL)
19517c478bd9Sstevel@tonic-gate 			*qop_state = 0;
19527c478bd9Sstevel@tonic-gate 
19537c478bd9Sstevel@tonic-gate 		killgssd_handle(clnt);
19547c478bd9Sstevel@tonic-gate 		GSSLOG0(1, "kgss_unseal: RPC call times out\n");
19557c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
19567c478bd9Sstevel@tonic-gate 	}
19577c478bd9Sstevel@tonic-gate 
19587c478bd9Sstevel@tonic-gate 	/* copy the rpc results into the return arguments */
19597c478bd9Sstevel@tonic-gate 
19607c478bd9Sstevel@tonic-gate 	if (minor_status != NULL)
19617c478bd9Sstevel@tonic-gate 		*minor_status = res.minor_status;
19627c478bd9Sstevel@tonic-gate 
19637c478bd9Sstevel@tonic-gate 	if (output_message_buffer != NULL) {
19647c478bd9Sstevel@tonic-gate 		output_message_buffer->length =
19657c478bd9Sstevel@tonic-gate 		    res.output_message_buffer.GSS_BUFFER_T_len;
19667c478bd9Sstevel@tonic-gate 
19677c478bd9Sstevel@tonic-gate 		output_message_buffer->value =
19687c478bd9Sstevel@tonic-gate 		    (void *) MALLOC(output_message_buffer->length);
19697c478bd9Sstevel@tonic-gate 		(void) memcpy(output_message_buffer->value,
19707c478bd9Sstevel@tonic-gate 		    res.output_message_buffer.GSS_BUFFER_T_val,
19717c478bd9Sstevel@tonic-gate 		    output_message_buffer->length);
19727c478bd9Sstevel@tonic-gate 	}
19737c478bd9Sstevel@tonic-gate 
19747c478bd9Sstevel@tonic-gate 	if (conf_state != NULL)
19757c478bd9Sstevel@tonic-gate 		*conf_state = res.conf_state;
19767c478bd9Sstevel@tonic-gate 
19777c478bd9Sstevel@tonic-gate 	if (qop_state != NULL)
19787c478bd9Sstevel@tonic-gate 		*qop_state = res.qop_state;
19797c478bd9Sstevel@tonic-gate 
19807c478bd9Sstevel@tonic-gate 	/*
19817c478bd9Sstevel@tonic-gate 	 * free the memory allocated for the results and return with the
19827c478bd9Sstevel@tonic-gate 	 * status received in the rpc call
19837c478bd9Sstevel@tonic-gate 	 */
19847c478bd9Sstevel@tonic-gate 
19857c478bd9Sstevel@tonic-gate 	clnt_freeres(clnt, xdr_gss_unseal_res, (caddr_t)&res);
19867c478bd9Sstevel@tonic-gate 	killgssd_handle(clnt);
19877c478bd9Sstevel@tonic-gate 	return (res.status);
19887c478bd9Sstevel@tonic-gate }
19897c478bd9Sstevel@tonic-gate 
19907c478bd9Sstevel@tonic-gate OM_uint32
19917c478bd9Sstevel@tonic-gate kgss_unseal(OM_uint32 *minor_status,
19927c478bd9Sstevel@tonic-gate 	const gss_ctx_id_t context_handle,
19937c478bd9Sstevel@tonic-gate 	const gss_buffer_t input_message_buffer,
19947c478bd9Sstevel@tonic-gate 	const gss_buffer_t output_message_buffer,
19957c478bd9Sstevel@tonic-gate 	int *conf_state,
19967c478bd9Sstevel@tonic-gate 	int *qop_state)
19977c478bd9Sstevel@tonic-gate {
19987c478bd9Sstevel@tonic-gate 
19997c478bd9Sstevel@tonic-gate 	if (context_handle == GSS_C_NO_CONTEXT)
20007c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
20017c478bd9Sstevel@tonic-gate 
20027c478bd9Sstevel@tonic-gate 	return (KGSS_UNSEAL(minor_status, context_handle, input_message_buffer,
20037c478bd9Sstevel@tonic-gate 	    output_message_buffer, conf_state, qop_state));
20047c478bd9Sstevel@tonic-gate }
20057c478bd9Sstevel@tonic-gate 
20067c478bd9Sstevel@tonic-gate OM_uint32
20077c478bd9Sstevel@tonic-gate kgss_display_status(minor_status,
20087c478bd9Sstevel@tonic-gate 		status_value,
20097c478bd9Sstevel@tonic-gate 		status_type,
20107c478bd9Sstevel@tonic-gate 		mech_type,
20117c478bd9Sstevel@tonic-gate 		message_context,
20127c478bd9Sstevel@tonic-gate 		status_string,
20137c478bd9Sstevel@tonic-gate 		uid)
20147c478bd9Sstevel@tonic-gate 	OM_uint32 *minor_status;
20157c478bd9Sstevel@tonic-gate 	OM_uint32 status_value;
20167c478bd9Sstevel@tonic-gate 	int status_type;
20177c478bd9Sstevel@tonic-gate 	const gss_OID mech_type;
20187c478bd9Sstevel@tonic-gate 	int *message_context;
20197c478bd9Sstevel@tonic-gate 	gss_buffer_t status_string;
20207c478bd9Sstevel@tonic-gate 	uid_t uid;
20217c478bd9Sstevel@tonic-gate {
20227c478bd9Sstevel@tonic-gate 	CLIENT *clnt;
20237c478bd9Sstevel@tonic-gate 
20247c478bd9Sstevel@tonic-gate 	gss_display_status_arg arg;
20257c478bd9Sstevel@tonic-gate 	gss_display_status_res res;
20267c478bd9Sstevel@tonic-gate 
20277c478bd9Sstevel@tonic-gate 	/* get the client handle to GSSD */
20287c478bd9Sstevel@tonic-gate 
20297c478bd9Sstevel@tonic-gate 	if ((clnt = getgssd_handle()) == NULL) {
20307c478bd9Sstevel@tonic-gate 	GSSLOG(1, "kgss_display_status: can't connect to server on %s\n",
20317c478bd9Sstevel@tonic-gate 			server);
20327c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
20337c478bd9Sstevel@tonic-gate 	}
20347c478bd9Sstevel@tonic-gate 
20357c478bd9Sstevel@tonic-gate 	/* copy the procedure arguments into the rpc arg parameter */
20367c478bd9Sstevel@tonic-gate 
20377c478bd9Sstevel@tonic-gate 	arg.uid = (OM_uint32) uid;
20387c478bd9Sstevel@tonic-gate 
20397c478bd9Sstevel@tonic-gate 	arg.status_value = status_value;
20407c478bd9Sstevel@tonic-gate 	arg.status_type = status_type;
20417c478bd9Sstevel@tonic-gate 
20427c478bd9Sstevel@tonic-gate 	arg.mech_type.GSS_OID_len = (uint_t)(mech_type != GSS_C_NULL_OID ?
20437c478bd9Sstevel@tonic-gate 						mech_type->length : 0);
20447c478bd9Sstevel@tonic-gate 	arg.mech_type.GSS_OID_val = (char *)(mech_type != GSS_C_NULL_OID ?
20457c478bd9Sstevel@tonic-gate 						mech_type->elements : 0);
20467c478bd9Sstevel@tonic-gate 
20477c478bd9Sstevel@tonic-gate 	arg.message_context = *message_context;
20487c478bd9Sstevel@tonic-gate 
20497c478bd9Sstevel@tonic-gate 	/* call the remote procedure */
20507c478bd9Sstevel@tonic-gate 
20517c478bd9Sstevel@tonic-gate 	if (message_context != NULL)
20527c478bd9Sstevel@tonic-gate 		*message_context = 0;
20537c478bd9Sstevel@tonic-gate 	if (status_string != NULL) {
20547c478bd9Sstevel@tonic-gate 		status_string->length = 0;
20557c478bd9Sstevel@tonic-gate 		status_string->value = NULL;
20567c478bd9Sstevel@tonic-gate 	}
20577c478bd9Sstevel@tonic-gate 
20587c478bd9Sstevel@tonic-gate 	bzero((caddr_t)&res, sizeof (res));
20597c478bd9Sstevel@tonic-gate 	if (gss_display_status_1(&arg, &res, clnt) != RPC_SUCCESS) {
20607c478bd9Sstevel@tonic-gate 
20617c478bd9Sstevel@tonic-gate 	/*
20627c478bd9Sstevel@tonic-gate 	 * if the RPC call times out, null out all return arguments, set
20637c478bd9Sstevel@tonic-gate 	 * minor_status to its maximum value, and return GSS_S_FAILURE
20647c478bd9Sstevel@tonic-gate 	 */
20657c478bd9Sstevel@tonic-gate 
20667c478bd9Sstevel@tonic-gate 		if (minor_status != NULL)
20677c478bd9Sstevel@tonic-gate 			*minor_status = DEFAULT_MINOR_STAT;
20687c478bd9Sstevel@tonic-gate 
20697c478bd9Sstevel@tonic-gate 		killgssd_handle(clnt);
20707c478bd9Sstevel@tonic-gate 		GSSLOG0(1, "kgss_display_status: RPC call time out\n");
20717c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
20727c478bd9Sstevel@tonic-gate 	}
20737c478bd9Sstevel@tonic-gate 
20747c478bd9Sstevel@tonic-gate 
20757c478bd9Sstevel@tonic-gate 	/* now process the results and pass them back to the caller */
20767c478bd9Sstevel@tonic-gate 
20777c478bd9Sstevel@tonic-gate 	if (res.status == GSS_S_COMPLETE) {
20787c478bd9Sstevel@tonic-gate 		if (minor_status != NULL)
20797c478bd9Sstevel@tonic-gate 			*minor_status = res.minor_status;
20807c478bd9Sstevel@tonic-gate 		if (message_context != NULL)
20817c478bd9Sstevel@tonic-gate 			*message_context = res.message_context;
20827c478bd9Sstevel@tonic-gate 		if (status_string != NULL) {
20837c478bd9Sstevel@tonic-gate 			status_string->length =
20847c478bd9Sstevel@tonic-gate 				(size_t)res.status_string.GSS_BUFFER_T_len;
20857c478bd9Sstevel@tonic-gate 			status_string->value =
20867c478bd9Sstevel@tonic-gate 				(void *) MALLOC(status_string->length);
20877c478bd9Sstevel@tonic-gate 			(void) memcpy(status_string->value,
20887c478bd9Sstevel@tonic-gate 				res.status_string.GSS_BUFFER_T_val,
20897c478bd9Sstevel@tonic-gate 				status_string->length);
20907c478bd9Sstevel@tonic-gate 		}
20917c478bd9Sstevel@tonic-gate 	}
20927c478bd9Sstevel@tonic-gate 
20937c478bd9Sstevel@tonic-gate 	clnt_freeres(clnt, xdr_gss_display_status_res, (caddr_t)&res);
20947c478bd9Sstevel@tonic-gate 	killgssd_handle(clnt);
20957c478bd9Sstevel@tonic-gate 	return (res.status);
20967c478bd9Sstevel@tonic-gate }
20977c478bd9Sstevel@tonic-gate 
20987c478bd9Sstevel@tonic-gate /*ARGSUSED*/
20997c478bd9Sstevel@tonic-gate OM_uint32
21007c478bd9Sstevel@tonic-gate kgss_indicate_mechs(minor_status,
21017c478bd9Sstevel@tonic-gate 			mech_set,
21027c478bd9Sstevel@tonic-gate 			uid)
21037c478bd9Sstevel@tonic-gate 	OM_uint32 *minor_status;
21047c478bd9Sstevel@tonic-gate 	gss_OID_set *mech_set;
21057c478bd9Sstevel@tonic-gate 	uid_t uid;
21067c478bd9Sstevel@tonic-gate {
21077c478bd9Sstevel@tonic-gate 	CLIENT *clnt;
21087c478bd9Sstevel@tonic-gate 	void *arg;
21097c478bd9Sstevel@tonic-gate 	gss_indicate_mechs_res res;
21107c478bd9Sstevel@tonic-gate 	int i;
21117c478bd9Sstevel@tonic-gate 
21127c478bd9Sstevel@tonic-gate 	/* get the client handle to GSSD */
21137c478bd9Sstevel@tonic-gate 
21147c478bd9Sstevel@tonic-gate 	if ((clnt = getgssd_handle()) == NULL) {
21157c478bd9Sstevel@tonic-gate 	GSSLOG(1, "kgss_indicate_mechs: can't connect to server on %s\n",
21167c478bd9Sstevel@tonic-gate 			server);
21177c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
21187c478bd9Sstevel@tonic-gate 	}
21197c478bd9Sstevel@tonic-gate 
21207c478bd9Sstevel@tonic-gate 	bzero((caddr_t)&res, sizeof (res));
21217c478bd9Sstevel@tonic-gate 	if (gss_indicate_mechs_1(&arg, &res, clnt) != RPC_SUCCESS) {
21227c478bd9Sstevel@tonic-gate 
21237c478bd9Sstevel@tonic-gate 	/*
21247c478bd9Sstevel@tonic-gate 	 * if the RPC call times out, null out all return arguments, set
21257c478bd9Sstevel@tonic-gate 	 * minor_status to its maximum value, and return GSS_S_FAILURE
21267c478bd9Sstevel@tonic-gate 	 */
21277c478bd9Sstevel@tonic-gate 
21287c478bd9Sstevel@tonic-gate 		if (minor_status != NULL)
21297c478bd9Sstevel@tonic-gate 			*minor_status = DEFAULT_MINOR_STAT;
21307c478bd9Sstevel@tonic-gate 		if (mech_set != NULL)
21317c478bd9Sstevel@tonic-gate 			*mech_set = NULL;
21327c478bd9Sstevel@tonic-gate 
21337c478bd9Sstevel@tonic-gate 		killgssd_handle(clnt);
21347c478bd9Sstevel@tonic-gate 		GSSLOG0(1, "kgss_indicate_mechs: RPC call times out\n");
21357c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
21367c478bd9Sstevel@tonic-gate 	}
21377c478bd9Sstevel@tonic-gate 
21387c478bd9Sstevel@tonic-gate 	/* copy the rpc results into the return arguments */
21397c478bd9Sstevel@tonic-gate 
21407c478bd9Sstevel@tonic-gate 	if (minor_status != NULL)
21417c478bd9Sstevel@tonic-gate 		*minor_status = res.minor_status;
21427c478bd9Sstevel@tonic-gate 
21437c478bd9Sstevel@tonic-gate 	if (mech_set != NULL) {
21447c478bd9Sstevel@tonic-gate 		*mech_set = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
21457c478bd9Sstevel@tonic-gate 		(*mech_set)->count = res.mech_set.GSS_OID_SET_len;
21467c478bd9Sstevel@tonic-gate 		(*mech_set)->elements = (void *)
21477c478bd9Sstevel@tonic-gate 			MALLOC ((*mech_set)->count * sizeof (gss_OID_desc));
21487c478bd9Sstevel@tonic-gate 		for (i = 0; i < (*mech_set)->count; i++) {
21497c478bd9Sstevel@tonic-gate 			(*mech_set)->elements[i].length =
21507c478bd9Sstevel@tonic-gate 				res.mech_set.GSS_OID_SET_val[i].GSS_OID_len;
21517c478bd9Sstevel@tonic-gate 			(*mech_set)->elements[i].elements = (void *)
21527c478bd9Sstevel@tonic-gate 				MALLOC ((*mech_set)->elements[i].length);
21537c478bd9Sstevel@tonic-gate 			(void) memcpy((*mech_set)->elements[i].elements,
21547c478bd9Sstevel@tonic-gate 				res.mech_set.GSS_OID_SET_val[i].GSS_OID_val,
21557c478bd9Sstevel@tonic-gate 				(*mech_set)->elements[i].length);
21567c478bd9Sstevel@tonic-gate 		}
21577c478bd9Sstevel@tonic-gate 	}
21587c478bd9Sstevel@tonic-gate 
21597c478bd9Sstevel@tonic-gate 	/*
21607c478bd9Sstevel@tonic-gate 	 * free the memory allocated for the results and return with the status
21617c478bd9Sstevel@tonic-gate 	 * received in the rpc call
21627c478bd9Sstevel@tonic-gate 	 */
21637c478bd9Sstevel@tonic-gate 
21647c478bd9Sstevel@tonic-gate 	clnt_freeres(clnt, xdr_gss_indicate_mechs_res, (caddr_t)&res);
21657c478bd9Sstevel@tonic-gate 	killgssd_handle(clnt);
21667c478bd9Sstevel@tonic-gate 	return (res.status);
21677c478bd9Sstevel@tonic-gate }
21687c478bd9Sstevel@tonic-gate 
21697c478bd9Sstevel@tonic-gate 
21707c478bd9Sstevel@tonic-gate OM_uint32
21717c478bd9Sstevel@tonic-gate kgss_inquire_cred_wrapped(minor_status,
21727c478bd9Sstevel@tonic-gate 		cred_handle,
21737c478bd9Sstevel@tonic-gate 		gssd_cred_verifier,
21747c478bd9Sstevel@tonic-gate 		name,
21757c478bd9Sstevel@tonic-gate 		lifetime,
21767c478bd9Sstevel@tonic-gate 		cred_usage,
21777c478bd9Sstevel@tonic-gate 		mechanisms,
21787c478bd9Sstevel@tonic-gate 		uid)
21797c478bd9Sstevel@tonic-gate 	OM_uint32 *minor_status;
21807c478bd9Sstevel@tonic-gate 	const gssd_cred_id_t cred_handle;
21817c478bd9Sstevel@tonic-gate 	OM_uint32 gssd_cred_verifier;
21827c478bd9Sstevel@tonic-gate 	gss_name_t *name;
21837c478bd9Sstevel@tonic-gate 	OM_uint32 *lifetime;
21847c478bd9Sstevel@tonic-gate 	int *cred_usage;
21857c478bd9Sstevel@tonic-gate 	gss_OID_set *mechanisms;
21867c478bd9Sstevel@tonic-gate 	uid_t uid;
21877c478bd9Sstevel@tonic-gate {
21887c478bd9Sstevel@tonic-gate 	CLIENT *clnt;
21897c478bd9Sstevel@tonic-gate 
21907c478bd9Sstevel@tonic-gate 	OM_uint32 	minor_status_temp;
21917c478bd9Sstevel@tonic-gate 	gss_buffer_desc	external_name;
21927c478bd9Sstevel@tonic-gate 	gss_OID_desc	name_type;
21937c478bd9Sstevel@tonic-gate 	int		i;
21947c478bd9Sstevel@tonic-gate 
21957c478bd9Sstevel@tonic-gate 	gss_inquire_cred_arg arg;
21967c478bd9Sstevel@tonic-gate 	gss_inquire_cred_res res;
21977c478bd9Sstevel@tonic-gate 
21987c478bd9Sstevel@tonic-gate 	/*
21997c478bd9Sstevel@tonic-gate 	 * NULL the params here once
22007c478bd9Sstevel@tonic-gate 	 * If there are errors then we won't
22017c478bd9Sstevel@tonic-gate 	 * have to do it for every error
22027c478bd9Sstevel@tonic-gate 	 * case
22037c478bd9Sstevel@tonic-gate 	 */
22047c478bd9Sstevel@tonic-gate 	if (minor_status != NULL)
22057c478bd9Sstevel@tonic-gate 		*minor_status = DEFAULT_MINOR_STAT;
22067c478bd9Sstevel@tonic-gate 	if (name != NULL)
22077c478bd9Sstevel@tonic-gate 		*name = NULL;
22087c478bd9Sstevel@tonic-gate 	if (lifetime != NULL)
22097c478bd9Sstevel@tonic-gate 		*lifetime = 0;
22107c478bd9Sstevel@tonic-gate 	if (cred_usage != NULL)
22117c478bd9Sstevel@tonic-gate 		*cred_usage = 0;
22127c478bd9Sstevel@tonic-gate 	if (mechanisms != NULL)
22137c478bd9Sstevel@tonic-gate 		*mechanisms = NULL;
22147c478bd9Sstevel@tonic-gate 
22157c478bd9Sstevel@tonic-gate 	/* get the client handle to GSSD */
22167c478bd9Sstevel@tonic-gate 
22177c478bd9Sstevel@tonic-gate 	if ((clnt = getgssd_handle()) == NULL) {
22187c478bd9Sstevel@tonic-gate 		GSSLOG(1, "kgss_inquire_cred: can't connect to server on %s\n",
22197c478bd9Sstevel@tonic-gate 			server);
22207c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
22217c478bd9Sstevel@tonic-gate 	}
22227c478bd9Sstevel@tonic-gate 
22237c478bd9Sstevel@tonic-gate 
22247c478bd9Sstevel@tonic-gate 	/* copy the procedure arguments into the rpc arg parameter */
22257c478bd9Sstevel@tonic-gate 
22267c478bd9Sstevel@tonic-gate 	arg.uid = (OM_uint32) uid;
22277c478bd9Sstevel@tonic-gate 
22287c478bd9Sstevel@tonic-gate 	arg.cred_handle.GSS_CRED_ID_T_len =
2229*d4f95bf4SRichard Lowe 	    cred_handle == GSSD_NO_CREDENTIAL ?
22307c478bd9Sstevel@tonic-gate 	    0 : (uint_t)sizeof (gssd_cred_id_t);
22317c478bd9Sstevel@tonic-gate 	arg.cred_handle.GSS_CRED_ID_T_val = (char *)&cred_handle;
22327c478bd9Sstevel@tonic-gate 	arg.gssd_cred_verifier = gssd_cred_verifier;
22337c478bd9Sstevel@tonic-gate 
22347c478bd9Sstevel@tonic-gate 	/* call the remote procedure */
22357c478bd9Sstevel@tonic-gate 
22367c478bd9Sstevel@tonic-gate 	bzero((caddr_t)&res, sizeof (res));
22377c478bd9Sstevel@tonic-gate 	if (gss_inquire_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
22387c478bd9Sstevel@tonic-gate 
22397c478bd9Sstevel@tonic-gate 		/*
22407c478bd9Sstevel@tonic-gate 		 * if the RPC call times out
22417c478bd9Sstevel@tonic-gate 		 * kill the handle and return GSS_S_FAILURE
22427c478bd9Sstevel@tonic-gate 		 * the parameters have been set to NULL already
22437c478bd9Sstevel@tonic-gate 		 */
22447c478bd9Sstevel@tonic-gate 
22457c478bd9Sstevel@tonic-gate 		killgssd_handle(clnt);
22467c478bd9Sstevel@tonic-gate 		GSSLOG0(1, "kgss_inquire_cred: RPC call times out\n");
22477c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
22487c478bd9Sstevel@tonic-gate 	}
22497c478bd9Sstevel@tonic-gate 
22507c478bd9Sstevel@tonic-gate 	/* copy the rpc results into the return arguments */
22517c478bd9Sstevel@tonic-gate 
22527c478bd9Sstevel@tonic-gate 	if (minor_status != NULL)
22537c478bd9Sstevel@tonic-gate 		*minor_status = res.minor_status;
22547c478bd9Sstevel@tonic-gate 
22557c478bd9Sstevel@tonic-gate 	/* convert name from external to internal format */
22567c478bd9Sstevel@tonic-gate 
22577c478bd9Sstevel@tonic-gate 	if (name != NULL) {
22587c478bd9Sstevel@tonic-gate 		external_name.length = res.name.GSS_BUFFER_T_len;
22597c478bd9Sstevel@tonic-gate 		external_name.value = res.name.GSS_BUFFER_T_val;
22607c478bd9Sstevel@tonic-gate 
22617c478bd9Sstevel@tonic-gate 		/*
22627c478bd9Sstevel@tonic-gate 		 * we can pass a pointer to res structure
22637c478bd9Sstevel@tonic-gate 		 * since gss_import_name treats the name_type
22647c478bd9Sstevel@tonic-gate 		 * parameter as read only and performs a copy
22657c478bd9Sstevel@tonic-gate 		 */
22667c478bd9Sstevel@tonic-gate 
22677c478bd9Sstevel@tonic-gate 		name_type.length = res.name_type.GSS_OID_len;
22687c478bd9Sstevel@tonic-gate 		name_type.elements = (void *)res.name_type.GSS_OID_val;
22697c478bd9Sstevel@tonic-gate 
22707c478bd9Sstevel@tonic-gate 		if (gss_import_name(&minor_status_temp, &external_name,
22717c478bd9Sstevel@tonic-gate 			&name_type, name) != GSS_S_COMPLETE) {
22727c478bd9Sstevel@tonic-gate 
22737c478bd9Sstevel@tonic-gate 			*minor_status = (OM_uint32) minor_status_temp;
22747c478bd9Sstevel@tonic-gate 			clnt_freeres(clnt, xdr_gss_inquire_cred_res,
22757c478bd9Sstevel@tonic-gate 							(caddr_t)&res);
22767c478bd9Sstevel@tonic-gate 			killgssd_handle(clnt);
22777c478bd9Sstevel@tonic-gate 			GSSLOG0(1, "kgss_inquire_cred: import name fails\n");
22787c478bd9Sstevel@tonic-gate 			return ((OM_uint32) GSS_S_FAILURE);
22797c478bd9Sstevel@tonic-gate 		}
22807c478bd9Sstevel@tonic-gate 	}
22817c478bd9Sstevel@tonic-gate 
22827c478bd9Sstevel@tonic-gate 	if (lifetime != NULL)
22837c478bd9Sstevel@tonic-gate 		*lifetime = res.lifetime;
22847c478bd9Sstevel@tonic-gate 
22857c478bd9Sstevel@tonic-gate 	if (cred_usage != NULL)
22867c478bd9Sstevel@tonic-gate 		*cred_usage = res.cred_usage;
22877c478bd9Sstevel@tonic-gate 
22887c478bd9Sstevel@tonic-gate 	if (res.status == GSS_S_COMPLETE &&
22897c478bd9Sstevel@tonic-gate 		res.mechanisms.GSS_OID_SET_len != 0 &&
22907c478bd9Sstevel@tonic-gate 		mechanisms != NULL) {
22917c478bd9Sstevel@tonic-gate 		*mechanisms = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
22927c478bd9Sstevel@tonic-gate 		(*mechanisms)->count =
22937c478bd9Sstevel@tonic-gate 			(int)res.mechanisms.GSS_OID_SET_len;
22947c478bd9Sstevel@tonic-gate 		(*mechanisms)->elements = (gss_OID)
22957c478bd9Sstevel@tonic-gate 			MALLOC(sizeof (gss_OID_desc) * (*mechanisms)->count);
22967c478bd9Sstevel@tonic-gate 
22977c478bd9Sstevel@tonic-gate 		for (i = 0; i < (*mechanisms)->count; i++) {
22987c478bd9Sstevel@tonic-gate 		    (*mechanisms)->elements[i].length = (OM_uint32)
22997c478bd9Sstevel@tonic-gate 			res.mechanisms.GSS_OID_SET_val[i].GSS_OID_len;
23007c478bd9Sstevel@tonic-gate 		    (*mechanisms)->elements[i].elements =
23017c478bd9Sstevel@tonic-gate 			(void *) MALLOC((*mechanisms)->elements[i].length);
23027c478bd9Sstevel@tonic-gate 		    (void) memcpy((*mechanisms)->elements[i].elements,
23037c478bd9Sstevel@tonic-gate 			res.mechanisms.GSS_OID_SET_val[i].GSS_OID_val,
23047c478bd9Sstevel@tonic-gate 			(*mechanisms)->elements[i].length);
23057c478bd9Sstevel@tonic-gate 		}
23067c478bd9Sstevel@tonic-gate 	} else {
23077c478bd9Sstevel@tonic-gate 		if (res.status == GSS_S_COMPLETE &&
23087c478bd9Sstevel@tonic-gate 			mechanisms != NULL)
23097c478bd9Sstevel@tonic-gate 			(*mechanisms) = NULL;
23107c478bd9Sstevel@tonic-gate 	}
23117c478bd9Sstevel@tonic-gate 	/*
23127c478bd9Sstevel@tonic-gate 	 * free the memory allocated for the results and return with the status
23137c478bd9Sstevel@tonic-gate 	 * received in the rpc call
23147c478bd9Sstevel@tonic-gate 	 */
23157c478bd9Sstevel@tonic-gate 
23167c478bd9Sstevel@tonic-gate 	clnt_freeres(clnt, xdr_gss_inquire_cred_res, (caddr_t)&res);
23177c478bd9Sstevel@tonic-gate 	killgssd_handle(clnt);
23187c478bd9Sstevel@tonic-gate 	return (res.status);
23197c478bd9Sstevel@tonic-gate 
23207c478bd9Sstevel@tonic-gate }
23217c478bd9Sstevel@tonic-gate 
23227c478bd9Sstevel@tonic-gate OM_uint32
23237c478bd9Sstevel@tonic-gate kgss_inquire_cred(minor_status,
23247c478bd9Sstevel@tonic-gate 			cred_handle,
23257c478bd9Sstevel@tonic-gate 			name,
23267c478bd9Sstevel@tonic-gate 			lifetime,
23277c478bd9Sstevel@tonic-gate 			cred_usage,
23287c478bd9Sstevel@tonic-gate 			mechanisms,
23297c478bd9Sstevel@tonic-gate 			uid)
23307c478bd9Sstevel@tonic-gate 	OM_uint32 *minor_status;
23317c478bd9Sstevel@tonic-gate 	const gss_cred_id_t cred_handle;
23327c478bd9Sstevel@tonic-gate 	gss_name_t *name;
23337c478bd9Sstevel@tonic-gate 	OM_uint32 *lifetime;
23347c478bd9Sstevel@tonic-gate 	int *cred_usage;
23357c478bd9Sstevel@tonic-gate 	gss_OID_set * mechanisms;
23367c478bd9Sstevel@tonic-gate 	uid_t uid;
23377c478bd9Sstevel@tonic-gate {
23387c478bd9Sstevel@tonic-gate 
23397c478bd9Sstevel@tonic-gate 	OM_uint32 gssd_cred_verifier;
23407c478bd9Sstevel@tonic-gate 	OM_uint32 gssd_cred_handle;
23417c478bd9Sstevel@tonic-gate 
23427c478bd9Sstevel@tonic-gate 	gssd_cred_verifier = KCRED_TO_CREDV(cred_handle);
23437c478bd9Sstevel@tonic-gate 	gssd_cred_handle = KCRED_TO_CRED(cred_handle);
23447c478bd9Sstevel@tonic-gate 
23457c478bd9Sstevel@tonic-gate 	return (kgss_inquire_cred_wrapped(minor_status,
23467c478bd9Sstevel@tonic-gate 			gssd_cred_handle, gssd_cred_verifier,
23477c478bd9Sstevel@tonic-gate 			name, lifetime, cred_usage, mechanisms, uid));
23487c478bd9Sstevel@tonic-gate }
23497c478bd9Sstevel@tonic-gate 
23507c478bd9Sstevel@tonic-gate OM_uint32
23517c478bd9Sstevel@tonic-gate kgss_inquire_cred_by_mech_wrapped(minor_status,
23527c478bd9Sstevel@tonic-gate 		cred_handle,
23537c478bd9Sstevel@tonic-gate 		gssd_cred_verifier,
23547c478bd9Sstevel@tonic-gate 		mech_type,
23557c478bd9Sstevel@tonic-gate 		uid)
23567c478bd9Sstevel@tonic-gate 	OM_uint32 *minor_status;
23577c478bd9Sstevel@tonic-gate 	gssd_cred_id_t cred_handle;
23587c478bd9Sstevel@tonic-gate 	OM_uint32 gssd_cred_verifier;
23597c478bd9Sstevel@tonic-gate 	gss_OID mech_type;
23607c478bd9Sstevel@tonic-gate 	uid_t uid;
23617c478bd9Sstevel@tonic-gate {
23627c478bd9Sstevel@tonic-gate 	CLIENT *clnt;
23637c478bd9Sstevel@tonic-gate 
23647c478bd9Sstevel@tonic-gate 	gss_inquire_cred_by_mech_arg arg;
23657c478bd9Sstevel@tonic-gate 	gss_inquire_cred_by_mech_res res;
23667c478bd9Sstevel@tonic-gate 
23677c478bd9Sstevel@tonic-gate 	/* get the client handle to GSSD */
23687c478bd9Sstevel@tonic-gate 
23697c478bd9Sstevel@tonic-gate 	if ((clnt = getgssd_handle()) == NULL) {
23707c478bd9Sstevel@tonic-gate 		GSSLOG(1, "kgss_inquire_cred: can't connect to server on %s\n",
23717c478bd9Sstevel@tonic-gate 			server);
23727c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
23737c478bd9Sstevel@tonic-gate 	}
23747c478bd9Sstevel@tonic-gate 
23757c478bd9Sstevel@tonic-gate 
23767c478bd9Sstevel@tonic-gate 	/* copy the procedure arguments into the rpc arg parameter */
23777c478bd9Sstevel@tonic-gate 
23787c478bd9Sstevel@tonic-gate 	arg.uid = (OM_uint32) uid;
23797c478bd9Sstevel@tonic-gate 
23807c478bd9Sstevel@tonic-gate 	arg.cred_handle.GSS_CRED_ID_T_len =
2381*d4f95bf4SRichard Lowe 	    cred_handle == GSSD_NO_CREDENTIAL ?
23827c478bd9Sstevel@tonic-gate 	    0 : (uint_t)sizeof (gssd_cred_id_t);
23837c478bd9Sstevel@tonic-gate 	arg.cred_handle.GSS_CRED_ID_T_val = (char *)&cred_handle;
23847c478bd9Sstevel@tonic-gate 	arg.gssd_cred_verifier = gssd_cred_verifier;
23857c478bd9Sstevel@tonic-gate 
23867c478bd9Sstevel@tonic-gate 	arg.mech_type.GSS_OID_len =
23877c478bd9Sstevel@tonic-gate 		(uint_t)(mech_type != GSS_C_NULL_OID ?
23887c478bd9Sstevel@tonic-gate 		mech_type->length : 0);
23897c478bd9Sstevel@tonic-gate 	arg.mech_type.GSS_OID_val =
23907c478bd9Sstevel@tonic-gate 		(char *)(mech_type != GSS_C_NULL_OID ?
23917c478bd9Sstevel@tonic-gate 		mech_type->elements : 0);
23927c478bd9Sstevel@tonic-gate 	/* call the remote procedure */
23937c478bd9Sstevel@tonic-gate 
23947c478bd9Sstevel@tonic-gate 	bzero((caddr_t)&res, sizeof (res));
23957c478bd9Sstevel@tonic-gate 	if (gss_inquire_cred_by_mech_1(&arg, &res, clnt) != RPC_SUCCESS) {
23967c478bd9Sstevel@tonic-gate 
23977c478bd9Sstevel@tonic-gate 	/*
23987c478bd9Sstevel@tonic-gate 	 * if the RPC call times out, null out all return arguments, set
23997c478bd9Sstevel@tonic-gate 	 * minor_status to its maximum value, and return GSS_S_FAILURE
24007c478bd9Sstevel@tonic-gate 	 */
24017c478bd9Sstevel@tonic-gate 
24027c478bd9Sstevel@tonic-gate 		if (minor_status != NULL)
24037c478bd9Sstevel@tonic-gate 			*minor_status = DEFAULT_MINOR_STAT;
24047c478bd9Sstevel@tonic-gate 		killgssd_handle(clnt);
24057c478bd9Sstevel@tonic-gate 		GSSLOG0(1, "kgss_inquire_cred: RPC call times out\n");
24067c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
24077c478bd9Sstevel@tonic-gate 	}
24087c478bd9Sstevel@tonic-gate 
24097c478bd9Sstevel@tonic-gate 	/* copy the rpc results into the return arguments */
24107c478bd9Sstevel@tonic-gate 
24117c478bd9Sstevel@tonic-gate 	if (minor_status != NULL)
24127c478bd9Sstevel@tonic-gate 		*minor_status = res.minor_status;
24137c478bd9Sstevel@tonic-gate 
24147c478bd9Sstevel@tonic-gate 	clnt_freeres(clnt, xdr_gss_inquire_cred_by_mech_res, (caddr_t)&res);
24157c478bd9Sstevel@tonic-gate 	killgssd_handle(clnt);
24167c478bd9Sstevel@tonic-gate 	return (res.status);
24177c478bd9Sstevel@tonic-gate 
24187c478bd9Sstevel@tonic-gate }
24197c478bd9Sstevel@tonic-gate 
24207c478bd9Sstevel@tonic-gate OM_uint32
24217c478bd9Sstevel@tonic-gate kgss_inquire_cred_by_mech(minor_status,
24227c478bd9Sstevel@tonic-gate 			cred_handle,
24237c478bd9Sstevel@tonic-gate 			mech_type,
24247c478bd9Sstevel@tonic-gate 			uid)
24257c478bd9Sstevel@tonic-gate 	OM_uint32 *minor_status;
24267c478bd9Sstevel@tonic-gate 	gss_cred_id_t cred_handle;
24277c478bd9Sstevel@tonic-gate 	gss_OID mech_type;
24287c478bd9Sstevel@tonic-gate 	uid_t uid;
24297c478bd9Sstevel@tonic-gate {
24307c478bd9Sstevel@tonic-gate 
24317c478bd9Sstevel@tonic-gate 	OM_uint32 gssd_cred_verifier;
24327c478bd9Sstevel@tonic-gate 	OM_uint32 gssd_cred_handle;
24337c478bd9Sstevel@tonic-gate 
24347c478bd9Sstevel@tonic-gate 	gssd_cred_verifier = KCRED_TO_CREDV(cred_handle);
24357c478bd9Sstevel@tonic-gate 	gssd_cred_handle = KCRED_TO_CRED(cred_handle);
24367c478bd9Sstevel@tonic-gate 
24377c478bd9Sstevel@tonic-gate 	return (kgss_inquire_cred_by_mech_wrapped(minor_status,
24387c478bd9Sstevel@tonic-gate 			gssd_cred_handle, gssd_cred_verifier,
24397c478bd9Sstevel@tonic-gate 			mech_type, uid));
24407c478bd9Sstevel@tonic-gate }
24417c478bd9Sstevel@tonic-gate 
24427c478bd9Sstevel@tonic-gate OM_uint32
24437c478bd9Sstevel@tonic-gate kgsscred_expname_to_unix_cred(expName, uidOut, gidOut, gids, gidsLen, uid)
24447c478bd9Sstevel@tonic-gate 	const gss_buffer_t expName;
24457c478bd9Sstevel@tonic-gate 	uid_t *uidOut;
24467c478bd9Sstevel@tonic-gate 	gid_t *gidOut;
24477c478bd9Sstevel@tonic-gate 	gid_t *gids[];
24487c478bd9Sstevel@tonic-gate 	int *gidsLen;
24497c478bd9Sstevel@tonic-gate 	uid_t uid;
24507c478bd9Sstevel@tonic-gate {
24517c478bd9Sstevel@tonic-gate 	CLIENT *clnt;
24527c478bd9Sstevel@tonic-gate 	gsscred_expname_to_unix_cred_arg args;
24537c478bd9Sstevel@tonic-gate 	gsscred_expname_to_unix_cred_res res;
24547c478bd9Sstevel@tonic-gate 
24557c478bd9Sstevel@tonic-gate 	/* check input/output parameters */
24567c478bd9Sstevel@tonic-gate 	if (expName == NULL || expName->value == NULL)
24577c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_READ);
24587c478bd9Sstevel@tonic-gate 
24597c478bd9Sstevel@tonic-gate 	if (uidOut == NULL)
24607c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
24617c478bd9Sstevel@tonic-gate 
24627c478bd9Sstevel@tonic-gate 	/* NULL out output parameters */
24637c478bd9Sstevel@tonic-gate 	*uidOut = UID_NOBODY;
24647c478bd9Sstevel@tonic-gate 	if (gidsLen)
24657c478bd9Sstevel@tonic-gate 		*gidsLen = 0;
24667c478bd9Sstevel@tonic-gate 
24677c478bd9Sstevel@tonic-gate 	if (gids)
24687c478bd9Sstevel@tonic-gate 		*gids = NULL;
24697c478bd9Sstevel@tonic-gate 
24707c478bd9Sstevel@tonic-gate 	/* get the client handle to gssd */
24717c478bd9Sstevel@tonic-gate 	if ((clnt = getgssd_handle()) == NULL)
24727c478bd9Sstevel@tonic-gate 	{
24737c478bd9Sstevel@tonic-gate 		GSSLOG(1, "kgsscred_expname_to_unix_cred:"
24747c478bd9Sstevel@tonic-gate 			" can't connect to server on %s\n", server);
24757c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
24767c478bd9Sstevel@tonic-gate 	}
24777c478bd9Sstevel@tonic-gate 
24787c478bd9Sstevel@tonic-gate 	/* copy the procedure arguments */
24797c478bd9Sstevel@tonic-gate 	args.uid = uid;
24807c478bd9Sstevel@tonic-gate 	args.expname.GSS_BUFFER_T_val = expName->value;
24817c478bd9Sstevel@tonic-gate 	args.expname.GSS_BUFFER_T_len = expName->length;
24827c478bd9Sstevel@tonic-gate 
24837c478bd9Sstevel@tonic-gate 	/* null out the return buffer and call the remote proc */
24847c478bd9Sstevel@tonic-gate 	bzero(&res, sizeof (res));
24857c478bd9Sstevel@tonic-gate 
24867c478bd9Sstevel@tonic-gate 	if (gsscred_expname_to_unix_cred_1(&args, &res, clnt) != RPC_SUCCESS)
24877c478bd9Sstevel@tonic-gate 	{
24887c478bd9Sstevel@tonic-gate 		killgssd_handle(clnt);
24897c478bd9Sstevel@tonic-gate 		GSSLOG0(1,
24907c478bd9Sstevel@tonic-gate 			"kgsscred_expname_to_unix_cred: RPC call times out\n");
24917c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
24927c478bd9Sstevel@tonic-gate 	}
24937c478bd9Sstevel@tonic-gate 
24947c478bd9Sstevel@tonic-gate 	/* copy the results into the result parameters */
24957c478bd9Sstevel@tonic-gate 	if (res.major == GSS_S_COMPLETE)
24967c478bd9Sstevel@tonic-gate 	{
24977c478bd9Sstevel@tonic-gate 		*uidOut = res.uid;
24987c478bd9Sstevel@tonic-gate 		if (gidOut)
24997c478bd9Sstevel@tonic-gate 			*gidOut = res.gid;
25007c478bd9Sstevel@tonic-gate 		if (gids && gidsLen)
25017c478bd9Sstevel@tonic-gate 		{
25027c478bd9Sstevel@tonic-gate 			*gids = res.gids.GSSCRED_GIDS_val;
25037c478bd9Sstevel@tonic-gate 			*gidsLen = res.gids.GSSCRED_GIDS_len;
25047c478bd9Sstevel@tonic-gate 			res.gids.GSSCRED_GIDS_val = NULL;
25057c478bd9Sstevel@tonic-gate 			res.gids.GSSCRED_GIDS_len = 0;
25067c478bd9Sstevel@tonic-gate 		}
25077c478bd9Sstevel@tonic-gate 	}
25087c478bd9Sstevel@tonic-gate 
25097c478bd9Sstevel@tonic-gate 	/* free RPC results */
25107c478bd9Sstevel@tonic-gate 	clnt_freeres(clnt, xdr_gsscred_expname_to_unix_cred_res, (caddr_t)&res);
25117c478bd9Sstevel@tonic-gate 	killgssd_handle(clnt);
25127c478bd9Sstevel@tonic-gate 
25137c478bd9Sstevel@tonic-gate 	return (res.major);
25147c478bd9Sstevel@tonic-gate } /* kgsscred_expname_to_unix_cred */
25157c478bd9Sstevel@tonic-gate 
25167c478bd9Sstevel@tonic-gate OM_uint32
25177c478bd9Sstevel@tonic-gate kgsscred_name_to_unix_cred(intName, mechType, uidOut, gidOut, gids,
25187c478bd9Sstevel@tonic-gate 				gidsLen, uid)
25197c478bd9Sstevel@tonic-gate 	const gss_name_t intName;
25207c478bd9Sstevel@tonic-gate 	const gss_OID mechType;
25217c478bd9Sstevel@tonic-gate 	uid_t *uidOut;
25227c478bd9Sstevel@tonic-gate 	gid_t *gidOut;
25237c478bd9Sstevel@tonic-gate 	gid_t *gids[];
25247c478bd9Sstevel@tonic-gate 	int *gidsLen;
25257c478bd9Sstevel@tonic-gate 	uid_t uid;
25267c478bd9Sstevel@tonic-gate {
25277c478bd9Sstevel@tonic-gate 	CLIENT *clnt;
25287c478bd9Sstevel@tonic-gate 	gsscred_name_to_unix_cred_arg args;
25297c478bd9Sstevel@tonic-gate 	gsscred_name_to_unix_cred_res res;
25307c478bd9Sstevel@tonic-gate 	OM_uint32 major, minor;
25317c478bd9Sstevel@tonic-gate 	gss_OID nameOid;
25327c478bd9Sstevel@tonic-gate 	gss_buffer_desc flatName = GSS_C_EMPTY_BUFFER;
25337c478bd9Sstevel@tonic-gate 
25347c478bd9Sstevel@tonic-gate 	/* check the input/output parameters */
25357c478bd9Sstevel@tonic-gate 	if (intName == NULL || mechType == NULL)
25367c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_READ);
25377c478bd9Sstevel@tonic-gate 
25387c478bd9Sstevel@tonic-gate 	if (uidOut == NULL)
25397c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
25407c478bd9Sstevel@tonic-gate 
25417c478bd9Sstevel@tonic-gate 	/* NULL out the output parameters */
25427c478bd9Sstevel@tonic-gate 	*uidOut = UID_NOBODY;
25437c478bd9Sstevel@tonic-gate 	if (gids)
25447c478bd9Sstevel@tonic-gate 		*gids = NULL;
25457c478bd9Sstevel@tonic-gate 
25467c478bd9Sstevel@tonic-gate 	if (gidsLen)
25477c478bd9Sstevel@tonic-gate 		*gidsLen = 0;
25487c478bd9Sstevel@tonic-gate 
25497c478bd9Sstevel@tonic-gate 	/* get the client handle to gssd */
25507c478bd9Sstevel@tonic-gate 	if ((clnt = getgssd_handle()) == NULL)
25517c478bd9Sstevel@tonic-gate 	{
25527c478bd9Sstevel@tonic-gate 		GSSLOG(1,
25537c478bd9Sstevel@tonic-gate 		"kgsscred_name_to_unix_cred: can't connect to server %s\n",
25547c478bd9Sstevel@tonic-gate 				server);
25557c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
25567c478bd9Sstevel@tonic-gate 	}
25577c478bd9Sstevel@tonic-gate 
25587c478bd9Sstevel@tonic-gate 	/* convert the name to flat representation */
25597c478bd9Sstevel@tonic-gate 	if ((major = gss_display_name(&minor, intName, &flatName, &nameOid))
25607c478bd9Sstevel@tonic-gate 			!= GSS_S_COMPLETE)
25617c478bd9Sstevel@tonic-gate 	{
25627c478bd9Sstevel@tonic-gate 		killgssd_handle(clnt);
25637c478bd9Sstevel@tonic-gate 		GSSLOG0(1, "kgsscred_name_to_unix_cred: display name failed\n");
25647c478bd9Sstevel@tonic-gate 		return (major);
25657c478bd9Sstevel@tonic-gate 	}
25667c478bd9Sstevel@tonic-gate 
25677c478bd9Sstevel@tonic-gate 	/* set the rpc parameters */
25687c478bd9Sstevel@tonic-gate 	args.uid = uid;
25697c478bd9Sstevel@tonic-gate 	args.pname.GSS_BUFFER_T_len = flatName.length;
25707c478bd9Sstevel@tonic-gate 	args.pname.GSS_BUFFER_T_val = flatName.value;
25717c478bd9Sstevel@tonic-gate 	args.name_type.GSS_OID_len = nameOid->length;
25727c478bd9Sstevel@tonic-gate 	args.name_type.GSS_OID_val = nameOid->elements;
25737c478bd9Sstevel@tonic-gate 	args.mech_type.GSS_OID_len = mechType->length;
25747c478bd9Sstevel@tonic-gate 	args.mech_type.GSS_OID_val = mechType->elements;
25757c478bd9Sstevel@tonic-gate 
25767c478bd9Sstevel@tonic-gate 	/* call the remote procedure */
25777c478bd9Sstevel@tonic-gate 	bzero(&res, sizeof (res));
25787c478bd9Sstevel@tonic-gate 	if (gsscred_name_to_unix_cred_1(&args, &res, clnt) != RPC_SUCCESS) {
25797c478bd9Sstevel@tonic-gate 		killgssd_handle(clnt);
25807c478bd9Sstevel@tonic-gate 		(void) gss_release_buffer(&minor, &flatName);
25817c478bd9Sstevel@tonic-gate 		GSSLOG0(1, "kgsscred_name_to_unix_cred: RPC call times out\n");
25827c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
25837c478bd9Sstevel@tonic-gate 	}
25847c478bd9Sstevel@tonic-gate 
25857c478bd9Sstevel@tonic-gate 	/* delete the flat name buffer */
25867c478bd9Sstevel@tonic-gate 	(void) gss_release_buffer(&minor, &flatName);
25877c478bd9Sstevel@tonic-gate 
25887c478bd9Sstevel@tonic-gate 	/* copy the output parameters on output */
25897c478bd9Sstevel@tonic-gate 	if (res.major == GSS_S_COMPLETE) {
25907c478bd9Sstevel@tonic-gate 		*uidOut = res.uid;
25917c478bd9Sstevel@tonic-gate 
25927c478bd9Sstevel@tonic-gate 		if (gidOut)
25937c478bd9Sstevel@tonic-gate 			*gidOut = res.gid;
25947c478bd9Sstevel@tonic-gate 		if (gids && gidsLen) {
25957c478bd9Sstevel@tonic-gate 			*gids = res.gids.GSSCRED_GIDS_val;
25967c478bd9Sstevel@tonic-gate 			*gidsLen = res.gids.GSSCRED_GIDS_len;
25977c478bd9Sstevel@tonic-gate 			res.gids.GSSCRED_GIDS_val = NULL;
25987c478bd9Sstevel@tonic-gate 			res.gids.GSSCRED_GIDS_len = 0;
25997c478bd9Sstevel@tonic-gate 		}
26007c478bd9Sstevel@tonic-gate 	}
26017c478bd9Sstevel@tonic-gate 
26027c478bd9Sstevel@tonic-gate 	/* delete RPC allocated memory */
26037c478bd9Sstevel@tonic-gate 	clnt_freeres(clnt, xdr_gsscred_name_to_unix_cred_res, (caddr_t)&res);
26047c478bd9Sstevel@tonic-gate 	killgssd_handle(clnt);
26057c478bd9Sstevel@tonic-gate 
26067c478bd9Sstevel@tonic-gate 	return (res.major);
26077c478bd9Sstevel@tonic-gate } /* kgsscred_name_to_unix_cred */
26087c478bd9Sstevel@tonic-gate 
26097c478bd9Sstevel@tonic-gate OM_uint32
26107c478bd9Sstevel@tonic-gate kgss_get_group_info(puid, gidOut, gids, gidsLen, uid)
26117c478bd9Sstevel@tonic-gate 	const uid_t puid;
26127c478bd9Sstevel@tonic-gate 	gid_t *gidOut;
26137c478bd9Sstevel@tonic-gate 	gid_t *gids[];
26147c478bd9Sstevel@tonic-gate 	int *gidsLen;
26157c478bd9Sstevel@tonic-gate 	uid_t uid;
26167c478bd9Sstevel@tonic-gate {
26177c478bd9Sstevel@tonic-gate 	CLIENT *clnt;
26187c478bd9Sstevel@tonic-gate 	gss_get_group_info_arg args;
26197c478bd9Sstevel@tonic-gate 	gss_get_group_info_res res;
26207c478bd9Sstevel@tonic-gate 
26217c478bd9Sstevel@tonic-gate 
26227c478bd9Sstevel@tonic-gate 	/* check the output parameters */
26237c478bd9Sstevel@tonic-gate 	if (gidOut == NULL || gids == NULL || gidsLen == NULL)
26247c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
26257c478bd9Sstevel@tonic-gate 
26267c478bd9Sstevel@tonic-gate 	/* get the client GSSD handle */
26277c478bd9Sstevel@tonic-gate 	if ((clnt = getgssd_handle()) == NULL) {
26287c478bd9Sstevel@tonic-gate 		GSSLOG(1,
26297c478bd9Sstevel@tonic-gate 			"kgss_get_group_info: can't connect to server on %s\n",
26307c478bd9Sstevel@tonic-gate 			server);
26317c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
26327c478bd9Sstevel@tonic-gate 	}
26337c478bd9Sstevel@tonic-gate 
26347c478bd9Sstevel@tonic-gate 	/* set the input parameters */
26357c478bd9Sstevel@tonic-gate 	args.uid = uid;
26367c478bd9Sstevel@tonic-gate 	args.puid = puid;
26377c478bd9Sstevel@tonic-gate 
26387c478bd9Sstevel@tonic-gate 	/* call the remote procedure */
26397c478bd9Sstevel@tonic-gate 	bzero(&res, sizeof (res));
26407c478bd9Sstevel@tonic-gate 	if (gss_get_group_info_1(&args, &res, clnt) != RPC_SUCCESS) {
26417c478bd9Sstevel@tonic-gate 		killgssd_handle(clnt);
26427c478bd9Sstevel@tonic-gate 		GSSLOG0(1, "kgss_get_group_info: RPC call times out\n");
26437c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
26447c478bd9Sstevel@tonic-gate 	}
26457c478bd9Sstevel@tonic-gate 
26467c478bd9Sstevel@tonic-gate 	/* copy the results */
26477c478bd9Sstevel@tonic-gate 	if (res.major == GSS_S_COMPLETE) {
26487c478bd9Sstevel@tonic-gate 		*gidOut = res.gid;
26497c478bd9Sstevel@tonic-gate 		*gids = res.gids.GSSCRED_GIDS_val;
26507c478bd9Sstevel@tonic-gate 		*gidsLen = res.gids.GSSCRED_GIDS_len;
26517c478bd9Sstevel@tonic-gate 		res.gids.GSSCRED_GIDS_val = NULL;
26527c478bd9Sstevel@tonic-gate 		res.gids.GSSCRED_GIDS_len = 0;
26537c478bd9Sstevel@tonic-gate 	}
26547c478bd9Sstevel@tonic-gate 
26557c478bd9Sstevel@tonic-gate 	/* no results to free */
26567c478bd9Sstevel@tonic-gate 	killgssd_handle(clnt);
26577c478bd9Sstevel@tonic-gate 
26587c478bd9Sstevel@tonic-gate 	return (res.major);
26597c478bd9Sstevel@tonic-gate } /* kgss_get_group_info */
26607c478bd9Sstevel@tonic-gate 
26617c478bd9Sstevel@tonic-gate static char *
26627c478bd9Sstevel@tonic-gate kgss_get_kmod(gss_OID mech_oid)
26637c478bd9Sstevel@tonic-gate {
26647c478bd9Sstevel@tonic-gate 	CLIENT *clnt;
26657c478bd9Sstevel@tonic-gate 	gss_get_kmod_arg args;
26667c478bd9Sstevel@tonic-gate 	gss_get_kmod_res res;
26677c478bd9Sstevel@tonic-gate 
26687c478bd9Sstevel@tonic-gate 
26697c478bd9Sstevel@tonic-gate 	/* get the client GSSD handle */
26707c478bd9Sstevel@tonic-gate 	if ((clnt = getgssd_handle()) == NULL) {
26717c478bd9Sstevel@tonic-gate 		GSSLOG(1, "kgss_get_kmod: can't connect to server on %s\n",
26727c478bd9Sstevel@tonic-gate 		    server);
26737c478bd9Sstevel@tonic-gate 		return (NULL);
26747c478bd9Sstevel@tonic-gate 	}
26757c478bd9Sstevel@tonic-gate 
26767c478bd9Sstevel@tonic-gate 	/* set the input parameters */
26777c478bd9Sstevel@tonic-gate 	args.mech_oid.GSS_OID_len = mech_oid->length;
26787c478bd9Sstevel@tonic-gate 	args.mech_oid.GSS_OID_val = mech_oid->elements;
26797c478bd9Sstevel@tonic-gate 
26807c478bd9Sstevel@tonic-gate 	/* call the remote procedure */
26817c478bd9Sstevel@tonic-gate 	bzero(&res, sizeof (res));
26827c478bd9Sstevel@tonic-gate 	if (gss_get_kmod_1(&args, &res, clnt) != RPC_SUCCESS) {
26837c478bd9Sstevel@tonic-gate 		killgssd_handle(clnt);
26847c478bd9Sstevel@tonic-gate 		GSSLOG0(1, "gss_get_kmod_1: RPC call times out\n");
26857c478bd9Sstevel@tonic-gate 		return (NULL);
26867c478bd9Sstevel@tonic-gate 	}
26877c478bd9Sstevel@tonic-gate 	/* no results to free */
26887c478bd9Sstevel@tonic-gate 	killgssd_handle(clnt);
26897c478bd9Sstevel@tonic-gate 
26907c478bd9Sstevel@tonic-gate 	if (res.module_follow == TRUE) {
26917c478bd9Sstevel@tonic-gate 		return (res.gss_get_kmod_res_u.modname);
26927c478bd9Sstevel@tonic-gate 	} else
26937c478bd9Sstevel@tonic-gate 		return (NULL);
26947c478bd9Sstevel@tonic-gate } /* kgss_get_kmod */
26957c478bd9Sstevel@tonic-gate 
26967c478bd9Sstevel@tonic-gate static gss_mechanism	kgss_mech_head;
26977c478bd9Sstevel@tonic-gate static gss_mechanism	kgss_mech_tail;
26987c478bd9Sstevel@tonic-gate kmutex_t	__kgss_mech_lock;
26997c478bd9Sstevel@tonic-gate 
27007c478bd9Sstevel@tonic-gate /*
27017c478bd9Sstevel@tonic-gate  * See if there is kernel mechanism module, and if so, attempt to
27027c478bd9Sstevel@tonic-gate  * load it and reset the pointer (gss_mechanism) to the sign/seal/etc.
27037c478bd9Sstevel@tonic-gate  * entry points to that of the kernel module.
27047c478bd9Sstevel@tonic-gate  */
27057c478bd9Sstevel@tonic-gate static void
27067c478bd9Sstevel@tonic-gate __kgss_reset_mech(gss_mechanism *mechp, gss_OID mech_oid)
27077c478bd9Sstevel@tonic-gate {
27087c478bd9Sstevel@tonic-gate 	gss_mechanism mech;
27097c478bd9Sstevel@tonic-gate 	char *kmod;
27107c478bd9Sstevel@tonic-gate 
27117c478bd9Sstevel@tonic-gate 	/*
27127c478bd9Sstevel@tonic-gate 	 * We can search the list without a mutex, becuase the list never
27137c478bd9Sstevel@tonic-gate 	 * shrinks and we always add to the end.
27147c478bd9Sstevel@tonic-gate 	 */
27157c478bd9Sstevel@tonic-gate 	mech = __kgss_get_mechanism(mech_oid);
27167c478bd9Sstevel@tonic-gate 	if (mech) {
27177c478bd9Sstevel@tonic-gate 		*mechp = mech;
27187c478bd9Sstevel@tonic-gate 		return;
27197c478bd9Sstevel@tonic-gate 	}
27207c478bd9Sstevel@tonic-gate 
27217c478bd9Sstevel@tonic-gate 	/*
27227c478bd9Sstevel@tonic-gate 	 * Get the module name from the kernel.
27237c478bd9Sstevel@tonic-gate 	 */
27247c478bd9Sstevel@tonic-gate 	kmod = kgss_get_kmod(mech_oid);
27257c478bd9Sstevel@tonic-gate 
27267c478bd9Sstevel@tonic-gate 	if (kmod) {
272743d5cd3dSjohnlev 		extern int modload(const char *, const char *);
27287c478bd9Sstevel@tonic-gate 		if (modload("misc/kgss", kmod) < 0) {
27297c478bd9Sstevel@tonic-gate 			/*
27307c478bd9Sstevel@tonic-gate 			 * Modload of 'kmod' failed, so log an
27317c478bd9Sstevel@tonic-gate 			 * appropriate comment
27327c478bd9Sstevel@tonic-gate 			 */
27337c478bd9Sstevel@tonic-gate 			cmn_err(CE_NOTE, "kgss_reset_mech: Algorithm modload "
27347c478bd9Sstevel@tonic-gate 			    "(%s) failed. Userland gssd will now handle "
27357c478bd9Sstevel@tonic-gate 			    "all GSSAPI calls, which may result in "
27367c478bd9Sstevel@tonic-gate 			    "reduced performance.\n", kmod);
27377c478bd9Sstevel@tonic-gate 		};
27387c478bd9Sstevel@tonic-gate 
27397c478bd9Sstevel@tonic-gate 		/*
27407c478bd9Sstevel@tonic-gate 		 * Allocated in the XDR routine called by gss_get_kmod_1().
27417c478bd9Sstevel@tonic-gate 		 */
27427c478bd9Sstevel@tonic-gate 		FREE(kmod, strlen(kmod)+1);
27437c478bd9Sstevel@tonic-gate 
27447c478bd9Sstevel@tonic-gate 		mech = __kgss_get_mechanism(mech_oid);
27457c478bd9Sstevel@tonic-gate 		if (mech) {
27467c478bd9Sstevel@tonic-gate 			*mechp = mech;
27477c478bd9Sstevel@tonic-gate 		}
27487c478bd9Sstevel@tonic-gate 
27497c478bd9Sstevel@tonic-gate 		/*
27507c478bd9Sstevel@tonic-gate 		 * If for some reason the module load didn't take,
27517c478bd9Sstevel@tonic-gate 		 * we return anyway and hope that the next context
27527c478bd9Sstevel@tonic-gate 		 * creation succeeds.
27537c478bd9Sstevel@tonic-gate 		 */
27547c478bd9Sstevel@tonic-gate 		return;
27557c478bd9Sstevel@tonic-gate 	}
27567c478bd9Sstevel@tonic-gate 
27577c478bd9Sstevel@tonic-gate 
27587c478bd9Sstevel@tonic-gate 	/*
27597c478bd9Sstevel@tonic-gate 	 * No kernel module, so enter this mech oid into the list
27607c478bd9Sstevel@tonic-gate 	 * using the default sign/seal/etc. operations that upcall to
27617c478bd9Sstevel@tonic-gate 	 * gssd.
27627c478bd9Sstevel@tonic-gate 	 */
27637c478bd9Sstevel@tonic-gate 	mutex_enter(&__kgss_mech_lock);
27647c478bd9Sstevel@tonic-gate 	mech = __kgss_get_mechanism(mech_oid);
27657c478bd9Sstevel@tonic-gate 	if (mech) {
27667c478bd9Sstevel@tonic-gate 		mutex_exit(&__kgss_mech_lock);
27677c478bd9Sstevel@tonic-gate 		*mechp = mech;
27687c478bd9Sstevel@tonic-gate 		return;
27697c478bd9Sstevel@tonic-gate 	}
27707c478bd9Sstevel@tonic-gate 
27717c478bd9Sstevel@tonic-gate 	/*
27727c478bd9Sstevel@tonic-gate 	 * Allocate space for the mechanism entry.
27737c478bd9Sstevel@tonic-gate 	 */
27747c478bd9Sstevel@tonic-gate 	mech = kmem_zalloc(sizeof (struct gss_config), KM_SLEEP);
27757c478bd9Sstevel@tonic-gate 
27767c478bd9Sstevel@tonic-gate 	/*
27777c478bd9Sstevel@tonic-gate 	 * Copy basic information from default mechanism struct.
27787c478bd9Sstevel@tonic-gate 	 */
27797c478bd9Sstevel@tonic-gate 	*mech = default_gc;
27807c478bd9Sstevel@tonic-gate 
27817c478bd9Sstevel@tonic-gate 	/*
27827c478bd9Sstevel@tonic-gate 	 * Record the real mech OID.
27837c478bd9Sstevel@tonic-gate 	 */
27847c478bd9Sstevel@tonic-gate 	mech->mech_type.length = mech_oid->length;
27857c478bd9Sstevel@tonic-gate 	mech->mech_type.elements = MALLOC(mech_oid->length);
27867c478bd9Sstevel@tonic-gate 	bcopy(mech_oid->elements,  mech->mech_type.elements, mech_oid->length);
27877c478bd9Sstevel@tonic-gate 
27887c478bd9Sstevel@tonic-gate 	/*
27897c478bd9Sstevel@tonic-gate 	 * Add it to the table.
27907c478bd9Sstevel@tonic-gate 	 */
27917c478bd9Sstevel@tonic-gate 	__kgss_add_mechanism(mech);
27927c478bd9Sstevel@tonic-gate 	mutex_exit(&__kgss_mech_lock);
27937c478bd9Sstevel@tonic-gate 	*mechp = mech;
27947c478bd9Sstevel@tonic-gate }
27957c478bd9Sstevel@tonic-gate 
27967c478bd9Sstevel@tonic-gate /*
27977c478bd9Sstevel@tonic-gate  * Called with __kgss_mech_lock held.
27987c478bd9Sstevel@tonic-gate  */
27997c478bd9Sstevel@tonic-gate void
28007c478bd9Sstevel@tonic-gate __kgss_add_mechanism(gss_mechanism mech)
28017c478bd9Sstevel@tonic-gate {
28027c478bd9Sstevel@tonic-gate 	gss_mechanism tmp;
28037c478bd9Sstevel@tonic-gate 
28047c478bd9Sstevel@tonic-gate 	tmp = kgss_mech_tail;
28057c478bd9Sstevel@tonic-gate 	kgss_mech_tail = mech;
28067c478bd9Sstevel@tonic-gate 
28077c478bd9Sstevel@tonic-gate 	if (tmp != NULL)
28087c478bd9Sstevel@tonic-gate 		tmp->next = mech;
28097c478bd9Sstevel@tonic-gate 
28107c478bd9Sstevel@tonic-gate 	if (kgss_mech_head == NULL)
28117c478bd9Sstevel@tonic-gate 		kgss_mech_head = mech;
28127c478bd9Sstevel@tonic-gate }
28137c478bd9Sstevel@tonic-gate 
28147c478bd9Sstevel@tonic-gate /*
28157c478bd9Sstevel@tonic-gate  *  given the mechs_array and a mechanism OID, return the
28167c478bd9Sstevel@tonic-gate  *  pointer to the mechanism, or NULL if that mechanism is
28177c478bd9Sstevel@tonic-gate  *  not supported.
28187c478bd9Sstevel@tonic-gate  */
28197c478bd9Sstevel@tonic-gate gss_mechanism
28207c478bd9Sstevel@tonic-gate __kgss_get_mechanism(gss_OID type)
28217c478bd9Sstevel@tonic-gate {
28227c478bd9Sstevel@tonic-gate 	gss_mechanism mech;
28237c478bd9Sstevel@tonic-gate 
28247c478bd9Sstevel@tonic-gate 	mech = kgss_mech_head;
28257c478bd9Sstevel@tonic-gate 
28267c478bd9Sstevel@tonic-gate 	/*
28277c478bd9Sstevel@tonic-gate 	 * Note that a reader can scan this list without the mutex held.
28287c478bd9Sstevel@tonic-gate 	 * This is safe because we always append, and never shrink the list.
28297c478bd9Sstevel@tonic-gate 	 * Moreover, the entry is fully initialized before it is ever
28307c478bd9Sstevel@tonic-gate 	 * added to the list.
28317c478bd9Sstevel@tonic-gate 	 */
28327c478bd9Sstevel@tonic-gate 	while (mech != NULL) {
28337c478bd9Sstevel@tonic-gate 		if ((mech->mech_type.length == type->length) &&
28347c478bd9Sstevel@tonic-gate 		    (bcmp(mech->mech_type.elements, type->elements,
28357c478bd9Sstevel@tonic-gate 		    type->length) == 0))
28367c478bd9Sstevel@tonic-gate 			return (mech);
28377c478bd9Sstevel@tonic-gate 
28387c478bd9Sstevel@tonic-gate 		mech = mech->next;
28397c478bd9Sstevel@tonic-gate 	}
28407c478bd9Sstevel@tonic-gate 	return (NULL);
28417c478bd9Sstevel@tonic-gate }
2842