diff usr/src/cmd/gss/gssd/gssd_clnt_stubs.c @ 0:c9caec207d52 b86

Initial porting based on b86
author Koji Uno <koji.uno@sun.com>
date Tue, 02 Jun 2009 18:56:50 +0900
parents
children 1a15d5aaf794
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/gss/gssd/gssd_clnt_stubs.c	Tue Jun 02 18:56:50 2009 +0900
@@ -0,0 +1,2685 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"@(#)gssd_clnt_stubs.c	1.43	05/06/08 SMI"
+
+/*
+ *  GSSAPI library stub module for gssd.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <mechglueP.h>
+#include "gssd.h"
+#include <rpc/rpc.h>
+
+#ifdef	_KERNEL
+#define	MALLOC(n) kmem_alloc((n), KM_SLEEP)
+#define	FREE(x, n) kmem_free((x), (n))
+#define	memcpy(dst, src, n) bcopy((src), (dst), (n))
+#define	clnt_pcreateerror(srv) printf("Cannot connect to server on %s\n", srv)
+
+#ifdef	DEBUG
+#ifndef	_SYS_CMN_ERR_H
+#define	_SYS_CMN_ERR_H
+#define	CE_NOTE 1
+#endif
+#include <sys/types.h>
+#include <sys/devops.h>
+#include <sys/open.h>
+#include <sys/stat.h>
+#include <sys/conf.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/uio.h>
+#endif /* DEBUG */
+
+#else /* !_KERNEL */
+#define	MALLOC(n) malloc(n)
+#define	FREE(x, n) free(x)
+#endif /* _KERNEL */
+#define	DEFAULT_MINOR_STAT	((OM_uint32) ~0)
+
+CLIENT  *clnt, *getgssd_handle();
+char *server = "localhost";
+
+OM_uint32
+kgss_acquire_cred_wrapped(minor_status,
+			desired_name,
+			time_req,
+			desired_mechs,
+			cred_usage,
+			output_cred_handle,
+			actual_mechs,
+			time_rec,
+			uid,
+			gssd_cred_verifier)
+	OM_uint32 *minor_status;
+	gss_name_t desired_name;
+	OM_uint32 time_req;
+	gss_OID_set desired_mechs;
+	int cred_usage;
+	gssd_cred_id_t *output_cred_handle;
+	gss_OID_set *actual_mechs;
+	OM_uint32 *time_rec;
+	uid_t uid;
+	OM_uint32 *gssd_cred_verifier;
+{
+	OM_uint32 minor_status_temp;
+	gss_buffer_desc	external_name;
+	gss_OID name_type;
+	int i;
+
+	gss_acquire_cred_arg arg;
+	gss_acquire_cred_res res;
+
+	/* get the client handle to GSSD */
+
+	if ((clnt = getgssd_handle()) == NULL) {
+		clnt_pcreateerror(server);
+		return (GSS_S_FAILURE);
+	}
+
+	/* convert the desired name from internal to external format */
+
+	if (gss_display_name(&minor_status_temp, desired_name, &external_name,
+				&name_type) != GSS_S_COMPLETE) {
+
+			*minor_status = (OM_uint32) minor_status_temp;
+			gss_release_buffer(&minor_status_temp, &external_name);
+		return ((OM_uint32) GSS_S_FAILURE);
+	}
+
+
+	/* copy the procedure arguments into the rpc arg parameter */
+
+	arg.uid = (OM_uint32)uid;
+
+	arg.desired_name.GSS_BUFFER_T_len = (uint_t)external_name.length;
+	arg.desired_name.GSS_BUFFER_T_val = (char *)external_name.value;
+
+	arg.name_type.GSS_OID_len =
+		name_type == GSS_C_NULL_OID ?
+			0 : (uint_t)name_type->length;
+
+	arg.name_type.GSS_OID_val =
+		name_type == GSS_C_NULL_OID ?
+			(char *)NULL : (char *)name_type->elements;
+
+	arg.time_req = time_req;
+
+	if (desired_mechs != GSS_C_NULL_OID_SET) {
+		arg.desired_mechs.GSS_OID_SET_len =
+			(uint_t)desired_mechs->count;
+		arg.desired_mechs.GSS_OID_SET_val = (GSS_OID *)
+			MALLOC(sizeof (GSS_OID) * desired_mechs->count);
+
+		for (i = 0; i < desired_mechs->count; i++) {
+			arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_len =
+				(uint_t)desired_mechs->elements[i].length;
+			arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val =
+				(char *)
+				MALLOC(desired_mechs->elements[i].length);
+			memcpy(arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val,
+				desired_mechs->elements[i].elements,
+				desired_mechs->elements[i].length);
+		}
+	} else
+		arg.desired_mechs.GSS_OID_SET_len = 0;
+
+	arg.cred_usage = cred_usage;
+
+	/* call the remote procedure */
+
+	memset(&res, 0, sizeof (res));
+	if (gss_acquire_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
+
+	/*
+	 * if the RPC call times out, null out all return arguments,
+	 * set minor_status to its maximum value, and return GSS_S_FAILURE
+	 */
+
+		if (minor_status != NULL)
+			*minor_status = 0xffffffff;
+		if (output_cred_handle != NULL)
+			*output_cred_handle = NULL;
+		if (actual_mechs != NULL)
+			*actual_mechs = NULL;
+		if (time_rec != NULL)
+			*time_rec = 0;
+
+		return (GSS_S_FAILURE);
+	}
+
+	/* free the allocated memory for the flattened name and desire_mechs */
+
+	gss_release_buffer(&minor_status_temp, &external_name);
+	for (i = 0; i < desired_mechs->count; i++)
+		FREE(arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val,
+			arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_len);
+	FREE(arg.desired_mechs.GSS_OID_SET_val,
+		arg.desired_mechs.GSS_OID_SET_len * sizeof (GSS_OID));
+
+	/* copy the rpc results into the return arguments */
+
+	if (minor_status != NULL)
+		*minor_status = res.minor_status;
+
+	if (output_cred_handle != NULL) {
+		 *output_cred_handle =
+		/*LINTED*/
+		*((gssd_cred_id_t *)res.output_cred_handle.GSS_CRED_ID_T_val);
+		 *gssd_cred_verifier = res.gssd_cred_verifier;
+	}
+
+	if (res.status == GSS_S_COMPLETE &&
+		res.actual_mechs.GSS_OID_SET_len != 0 &&
+		actual_mechs != NULL) {
+		*actual_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
+		(*actual_mechs)->count =
+			(int)res.actual_mechs.GSS_OID_SET_len;
+		(*actual_mechs)->elements = (gss_OID)
+			MALLOC(sizeof (gss_OID_desc) * (*actual_mechs)->count);
+
+		for (i = 0; i < (*actual_mechs)->count; i++) {
+			(*actual_mechs)->elements[i].length = (OM_uint32)
+			res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_len;
+			(*actual_mechs)->elements[i].elements =
+			(void *) MALLOC((*actual_mechs)->elements[i].length);
+			memcpy((*actual_mechs)->elements[i].elements,
+			res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_val,
+			(*actual_mechs)->elements[i].length);
+		}
+	} else {
+		if (res.status == GSS_S_COMPLETE && actual_mechs != NULL)
+			(*actual_mechs)->count = 0;
+	}
+
+	if (time_rec != NULL)
+		*time_rec = res.time_rec;
+
+	/*
+	 * free the memory allocated for the results and return with the status
+	 * received in the rpc call
+	 */
+
+	clnt_freeres(clnt, xdr_gss_acquire_cred_res, (caddr_t)&res);
+	return (res.status);
+}
+
+OM_uint32
+kgss_acquire_cred(minor_status,
+		desired_name,
+		time_req,
+		desired_mechs,
+		cred_usage,
+		output_cred_handle,
+		actual_mechs,
+		time_rec,
+		uid)
+	OM_uint32 *minor_status;
+	gss_name_t desired_name;
+	OM_uint32 time_req;
+	gss_OID_set desired_mechs;
+	int cred_usage;
+	gss_cred_id_t *output_cred_handle;
+	gss_OID_set *actual_mechs;
+	OM_uint32 *time_rec;
+	uid_t uid;
+{
+
+		OM_uint32	err;
+		struct kgss_cred *kcred;
+
+		kcred = KGSS_CRED_ALLOC();
+		*output_cred_handle = (gss_cred_id_t)kcred;
+		err = kgss_acquire_cred_wrapped(minor_status,
+					desired_name, time_req,
+					desired_mechs, cred_usage,
+					&kcred->gssd_cred, actual_mechs,
+					time_rec, uid,
+					&kcred->gssd_cred_verifier);
+		if (GSS_ERROR(err)) {
+			KGSS_CRED_FREE(kcred);
+			*output_cred_handle = GSS_C_NO_CREDENTIAL;
+		}
+		return (err);
+}
+
+OM_uint32
+kgss_add_cred_wrapped(minor_status,
+			input_cred_handle,
+			gssd_cred_verifier,
+			desired_name,
+			desired_mech_type,
+			cred_usage,
+			initiator_time_req,
+			acceptor_time_req,
+			actual_mechs,
+			initiator_time_rec,
+			acceptor_time_rec,
+			uid)
+	OM_uint32 *minor_status;
+	gssd_cred_id_t input_cred_handle;
+	OM_uint32 gssd_cred_verifier;
+	gss_name_t desired_name;
+	gss_OID desired_mech_type;
+	int cred_usage;
+	int initiator_time_req;
+	int acceptor_time_req;
+	gss_OID_set *actual_mechs;
+	OM_uint32 *initiator_time_rec;
+	OM_uint32 *acceptor_time_rec;
+	uid_t uid;
+{
+	CLIENT *clnt;
+
+	OM_uint32 	minor_status_temp;
+	gss_buffer_desc	external_name;
+	gss_OID		name_type;
+	int		i;
+
+	gss_add_cred_arg arg;
+	gss_add_cred_res res;
+
+	/* get the client handle to GSSD */
+
+	if ((clnt = getgssd_handle()) == NULL) {
+		clnt_pcreateerror(server);
+		return (GSS_S_FAILURE);
+	}
+
+
+	/* convert the desired name from internal to external format */
+
+	if (gss_display_name(&minor_status_temp, desired_name, &external_name,
+				&name_type) != GSS_S_COMPLETE) {
+
+		*minor_status = (OM_uint32) minor_status_temp;
+		(void) gss_release_buffer(&minor_status_temp, &external_name);
+		clnt_pcreateerror(server);
+		return ((OM_uint32) GSS_S_FAILURE);
+	}
+
+
+	/* copy the procedure arguments into the rpc arg parameter */
+
+	arg.uid = (OM_uint32) uid;
+	arg.input_cred_handle.GSS_CRED_ID_T_len =
+			input_cred_handle ==
+			(gssd_cred_id_t)GSS_C_NO_CREDENTIAL ?
+			0 : (uint_t)sizeof (gssd_cred_id_t);
+	arg.input_cred_handle.GSS_CRED_ID_T_val =
+						(char *)&input_cred_handle;
+	arg.gssd_cred_verifier = gssd_cred_verifier;
+	arg.desired_name.GSS_BUFFER_T_len = (uint_t)external_name.length;
+	arg.desired_name.GSS_BUFFER_T_val = (char *)external_name.value;
+	arg.name_type.GSS_OID_len =
+		name_type == GSS_C_NULL_OID ?
+			0 : (uint_t)name_type->length;
+	arg.name_type.GSS_OID_val =
+		name_type == GSS_C_NULL_OID ?
+			(char *)NULL : (char *)name_type->elements;
+
+	arg.desired_mech_type.GSS_OID_len =
+		(uint_t)(desired_mech_type != GSS_C_NULL_OID ?
+		desired_mech_type->length : 0);
+	arg.desired_mech_type.GSS_OID_val =
+		(char *)(desired_mech_type != GSS_C_NULL_OID ?
+		desired_mech_type->elements : 0);
+	arg.cred_usage = cred_usage;
+	arg.initiator_time_req = initiator_time_req;
+	arg.acceptor_time_req = acceptor_time_req;
+
+	/* call the remote procedure */
+
+	bzero((caddr_t)&res, sizeof (res));
+	if (gss_add_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
+
+		/*
+		 * if the RPC call times out, null out all return arguments,
+		 * set minor_status to its maximum value, and return
+		 * GSS_S_FAILURE
+		 */
+
+		if (minor_status != NULL)
+			*minor_status = DEFAULT_MINOR_STAT;
+		if (actual_mechs != NULL)
+			*actual_mechs = NULL;
+		if (initiator_time_rec != NULL)
+			*initiator_time_rec = 0;
+		if (acceptor_time_rec != NULL)
+			*acceptor_time_rec = 0;
+		return (GSS_S_FAILURE);
+	}
+
+	/* free the allocated memory for the flattened name */
+
+	(void) gss_release_buffer(&minor_status_temp, &external_name);
+
+	/* copy the rpc results into the return arguments */
+
+	if (minor_status != NULL)
+		*minor_status = res.minor_status;
+
+	if (res.status == GSS_S_COMPLETE &&
+		res.actual_mechs.GSS_OID_SET_len != 0 &&
+		actual_mechs != NULL) {
+		*actual_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
+		(*actual_mechs)->count =
+					(int)res.actual_mechs.GSS_OID_SET_len;
+		(*actual_mechs)->elements = (gss_OID)
+			MALLOC(sizeof (gss_OID_desc) * (*actual_mechs)->count);
+
+		for (i = 0; i < (*actual_mechs)->count; i++) {
+		    (*actual_mechs)->elements[i].length = (OM_uint32)
+			res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_len;
+		    (*actual_mechs)->elements[i].elements =
+			(void *) MALLOC((*actual_mechs)->elements[i].length);
+		    memcpy((*actual_mechs)->elements[i].elements,
+			res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_val,
+			(*actual_mechs)->elements[i].length);
+		}
+	} else {
+		if (res.status == GSS_S_COMPLETE &&
+			actual_mechs != NULL)
+			(*actual_mechs)->count = 0;
+	}
+	if (initiator_time_rec != NULL)
+		*initiator_time_rec = res.initiator_time_rec;
+	if (acceptor_time_rec != NULL)
+		*acceptor_time_rec = res.acceptor_time_rec;
+
+	/*
+	 * free the memory allocated for the results and return with the status
+	 * received in the rpc call
+	 */
+
+	clnt_freeres(clnt, xdr_gss_add_cred_res, (caddr_t)&res);
+	return (res.status);
+
+}
+
+OM_uint32
+kgss_add_cred(minor_status,
+			input_cred_handle,
+			desired_name,
+			desired_mech_type,
+			cred_usage,
+			initiator_time_req,
+			acceptor_time_req,
+			actual_mechs,
+			initiator_time_rec,
+			acceptor_time_rec,
+			uid)
+	OM_uint32 *minor_status;
+	gss_cred_id_t input_cred_handle;
+	gss_name_t desired_name;
+	gss_OID desired_mech_type;
+	int cred_usage;
+	int initiator_time_req;
+	int acceptor_time_req;
+	gss_OID_set *actual_mechs;
+	OM_uint32 *initiator_time_rec;
+	OM_uint32 *acceptor_time_rec;
+	uid_t uid;
+{
+
+	OM_uint32	err;
+	OM_uint32 gssd_cred_verifier;
+	gssd_cred_id_t gssd_input_cred_handle;
+
+
+	if (input_cred_handle != GSS_C_NO_CREDENTIAL) {
+		gssd_cred_verifier = KCRED_TO_CREDV(input_cred_handle);
+		gssd_input_cred_handle = KCRED_TO_CRED(input_cred_handle);
+	} else
+		gssd_input_cred_handle = (gssd_cred_id_t)GSS_C_NO_CREDENTIAL;
+
+	err = kgss_add_cred_wrapped(minor_status, gssd_input_cred_handle,
+			gssd_cred_verifier, desired_name, desired_mech_type,
+			cred_usage, initiator_time_req, acceptor_time_req,
+			actual_mechs, initiator_time_rec,
+			acceptor_time_rec, uid);
+	return (err);
+}
+
+OM_uint32
+kgss_release_cred_wrapped(minor_status,
+		cred_handle,
+		uid,
+		gssd_cred_verifier)
+OM_uint32 *minor_status;
+gssd_cred_id_t *cred_handle;
+uid_t uid;
+OM_uint32 gssd_cred_verifier;
+{
+
+	gss_release_cred_arg arg;
+	gss_release_cred_res res;
+
+
+	/* get the client handle to GSSD */
+	if ((clnt = getgssd_handle()) == NULL) {
+		clnt_pcreateerror(server);
+		return (GSS_S_FAILURE);
+	}
+
+	/* copy the procedure arguments into the rpc arg parameter */
+
+	arg.uid = (OM_uint32) uid;
+	arg.gssd_cred_verifier = gssd_cred_verifier;
+
+	if (cred_handle != NULL) {
+		arg.cred_handle.GSS_CRED_ID_T_len =
+			(uint_t)sizeof (gssd_cred_id_t);
+		arg.cred_handle.GSS_CRED_ID_T_val = (char *)cred_handle;
+	} else
+		arg.cred_handle.GSS_CRED_ID_T_len = 0;
+
+	/* call the remote procedure */
+
+	memset(&res, 0, sizeof (res));
+	if (gss_release_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
+
+		/*
+		 * if the RPC call times out, null out all return arguments,
+		 * set minor_status to its max value, and return GSS_S_FAILURE
+		 */
+
+		if (minor_status != NULL)
+			*minor_status = 0xffffffff;
+		if (cred_handle != NULL)
+			*cred_handle = NULL;
+
+		return (GSS_S_FAILURE);
+	}
+
+	/* if the release succeeded, null out the cred_handle */
+	if (res.status == GSS_S_COMPLETE && cred_handle != NULL)
+		*cred_handle = NULL;
+
+	/* copy the rpc results into the return arguments */
+	if (minor_status != NULL)
+		*minor_status = res.minor_status;
+
+	/* return with status returned in rpc call */
+	return (res.status);
+}
+
+OM_uint32
+kgss_release_cred(minor_status,
+			cred_handle,
+			uid)
+	OM_uint32 *minor_status;
+	gss_cred_id_t *cred_handle;
+	uid_t uid;
+
+{
+
+		OM_uint32	err;
+		struct kgss_cred *kcred;
+
+		if (*cred_handle == GSS_C_NO_CREDENTIAL)
+			return (GSS_S_COMPLETE);
+		else
+			kcred = KCRED_TO_KGSS_CRED(*cred_handle);
+
+		err = kgss_release_cred_wrapped(minor_status, &kcred->gssd_cred,
+			uid, kcred->gssd_cred_verifier);
+		KGSS_CRED_FREE(kcred);
+		*cred_handle = GSS_C_NO_CREDENTIAL;
+		return (err);
+}
+
+OM_uint32
+kgss_init_sec_context_wrapped(minor_status,
+			claimant_cred_handle,
+			gssd_cred_verifier,
+			context_handle,
+			gssd_context_verifier,
+		target_name,
+		mech_type,
+		req_flags,
+		time_req,
+		input_chan_bindings,
+		input_token,
+		actual_mech_type,
+		output_token,
+		ret_flags,
+		time_rec,
+		uid)
+	OM_uint32 *minor_status;
+	gssd_cred_id_t claimant_cred_handle;
+	OM_uint32 gssd_cred_verifier;
+	OM_uint32 *context_handle;
+	OM_uint32 *gssd_context_verifier;
+	gss_name_t target_name;
+	gss_OID mech_type;
+	int req_flags;
+	OM_uint32 time_req;
+	gss_channel_bindings_t input_chan_bindings;
+	gss_buffer_t input_token;
+	gss_OID *actual_mech_type;
+	gss_buffer_t output_token;
+	int *ret_flags;
+	OM_uint32 *time_rec;
+	uid_t uid;
+{
+	OM_uint32 minor_status_temp;
+	gss_buffer_desc external_name;
+	gss_OID name_type;
+	gss_init_sec_context_arg arg;
+	gss_init_sec_context_res res;
+
+	/* get the client handle to GSSD */
+
+	if ((clnt = getgssd_handle()) == NULL) {
+		clnt_pcreateerror(server);
+		return (GSS_S_FAILURE);
+	}
+
+	/* convert the target name from internal to external format */
+
+	if (gss_display_name(&minor_status_temp, target_name,
+			&external_name, &name_type) != GSS_S_COMPLETE) {
+
+		*minor_status = (OM_uint32) minor_status_temp;
+		return ((OM_uint32) GSS_S_FAILURE);
+	}
+
+
+/* copy the procedure arguments into the rpc arg parameter */
+
+	arg.uid = (OM_uint32) uid;
+
+	arg.context_handle.GSS_CTX_ID_T_len =
+		*context_handle == (OM_uint32) GSS_C_NO_CONTEXT ? 0 :
+		(uint_t)sizeof (OM_uint32);
+	arg.context_handle.GSS_CTX_ID_T_val =  (char *)context_handle;
+	arg.gssd_context_verifier = *gssd_context_verifier;
+
+	arg.claimant_cred_handle.GSS_CRED_ID_T_len =
+		claimant_cred_handle == (gssd_cred_id_t)GSS_C_NO_CREDENTIAL ?
+		0 : (uint_t)sizeof (gssd_cred_id_t);
+	arg.claimant_cred_handle.GSS_CRED_ID_T_val =
+		(char *)&claimant_cred_handle;
+	arg.gssd_cred_verifier =  gssd_cred_verifier;
+
+	arg.target_name.GSS_BUFFER_T_len = (uint_t)external_name.length;
+	arg.target_name.GSS_BUFFER_T_val = (char *)external_name.value;
+
+	arg.name_type.GSS_OID_len =
+		name_type == GSS_C_NULL_OID ?
+		0 : (uint_t)name_type->length;
+
+	arg.name_type.GSS_OID_val =
+		name_type == GSS_C_NULL_OID ?
+		(char *)NULL : (char *)name_type->elements;
+
+	arg.mech_type.GSS_OID_len = (uint_t)(mech_type != GSS_C_NULL_OID ?
+				mech_type->length : 0);
+	arg.mech_type.GSS_OID_val = (char *)(mech_type != GSS_C_NULL_OID ?
+				mech_type->elements : 0);
+
+	arg.req_flags = req_flags;
+
+	arg.time_req = time_req;
+
+	if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) {
+		arg.input_chan_bindings.present = YES;
+		arg.input_chan_bindings.initiator_addrtype =
+			input_chan_bindings->initiator_addrtype;
+		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len =
+			(uint_t)input_chan_bindings->initiator_address.length;
+		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val =
+			(void *) input_chan_bindings->initiator_address.value;
+		arg.input_chan_bindings.acceptor_addrtype =
+			input_chan_bindings->acceptor_addrtype;
+		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len =
+			(uint_t)input_chan_bindings->acceptor_address.length;
+		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val =
+			(void *) input_chan_bindings->acceptor_address.value;
+		arg.input_chan_bindings.application_data.GSS_BUFFER_T_len =
+			(uint_t)input_chan_bindings->application_data.length;
+		arg.input_chan_bindings.application_data.GSS_BUFFER_T_val =
+			(void *) input_chan_bindings->application_data.value;
+	} else {
+		arg.input_chan_bindings.present = NO;
+		arg.input_chan_bindings.initiator_addrtype = 0;
+		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = 0;
+		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = 0;
+		arg.input_chan_bindings.acceptor_addrtype = 0;
+		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = 0;
+		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = 0;
+		arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = 0;
+		arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = 0;
+	}
+
+	arg.input_token.GSS_BUFFER_T_len = (uint_t)
+		(input_token != GSS_C_NO_BUFFER ? input_token->length : 0);
+	arg.input_token.GSS_BUFFER_T_val = (char *)
+		(input_token != GSS_C_NO_BUFFER ? input_token->value : 0);
+
+	/* initialize the output parameters to empty values */
+	if (minor_status != NULL)
+		*minor_status = 0xffffffff;
+	if (actual_mech_type != NULL)
+		*actual_mech_type = NULL;
+	if (output_token != NULL)
+		output_token->length = 0;
+	if (ret_flags != NULL)
+		*ret_flags = 0;
+	if (time_rec != NULL)
+		*time_rec = 0;
+
+	/* call the remote procedure */
+	memset(&res, 0, sizeof (res));
+	if (gss_init_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
+
+		/* free the allocated memory for the flattened name */
+		gss_release_buffer(&minor_status_temp, &external_name);
+
+		return (GSS_S_FAILURE);
+	}
+
+
+	/* free the allocated memory for the flattened name */
+	gss_release_buffer(&minor_status_temp, &external_name);
+
+	/* if the call was successful, copy out the results */
+	if (res.status == (OM_uint32) GSS_S_COMPLETE ||
+		res.status == (OM_uint32) GSS_S_CONTINUE_NEEDED) {
+		/*
+		 * copy the rpc results into the return arguments
+		 * on CONTINUE_NEEDED only the output token, minor
+		 * code and ctxt handle are ready.
+		 */
+		if (minor_status != NULL)
+			*minor_status = res.minor_status;
+		/*LINTED*/
+		*context_handle = *((OM_uint32 *)
+			res.context_handle.GSS_CTX_ID_T_val);
+
+		/*LINTED*/
+		*context_handle = *((OM_uint32 *)
+			res.context_handle.GSS_CTX_ID_T_val);
+		*gssd_context_verifier = res.gssd_context_verifier;
+
+		if (output_token != NULL) {
+			output_token->length =
+				(size_t)res.output_token.GSS_BUFFER_T_len;
+			output_token->value =
+				(void *)res.output_token.GSS_BUFFER_T_val;
+			res.output_token.GSS_BUFFER_T_val = NULL;
+			res.output_token.GSS_BUFFER_T_len = 0;
+		}
+
+		/* the rest of the parameters is only ready on COMPLETE */
+		if (res.status == GSS_S_COMPLETE) {
+			if (actual_mech_type != NULL) {
+				*actual_mech_type = (gss_OID)
+					MALLOC(sizeof (gss_OID_desc));
+				(*actual_mech_type)->length = (OM_UINT32)
+					res.actual_mech_type.GSS_OID_len;
+				(*actual_mech_type)->elements = (void *)
+					MALLOC((*actual_mech_type)->length);
+				memcpy((*actual_mech_type)->elements, (void *)
+					res.actual_mech_type.GSS_OID_val,
+					(*actual_mech_type)->length);
+			}
+
+
+			if (ret_flags != NULL)
+				*ret_flags = res.ret_flags;
+
+			if (time_rec != NULL)
+				*time_rec = res.time_rec;
+		}
+	}
+
+
+	/*
+	 * free the memory allocated for the results and return with the
+	 * status received in the rpc call.
+	 */
+
+	clnt_freeres(clnt, xdr_gss_init_sec_context_res, (caddr_t)&res);
+	return (res.status);
+}
+OM_uint32
+kgss_init_sec_context(
+		OM_uint32 *minor_status,
+		gss_cred_id_t claimant_cred_handle,
+		gss_ctx_id_t *context_handle,
+		gss_name_t target_name,
+		gss_OID mech_type,
+		int req_flags,
+		OM_uint32 time_req,
+		gss_channel_bindings_t input_chan_bindings,
+		gss_buffer_t input_token,
+		gss_OID *actual_mech_type,
+		gss_buffer_t output_token,
+		int *ret_flags,
+		OM_uint32 *time_rec,
+		uid_t uid)
+{
+		OM_uint32	err;
+		struct kgss_ctx	*kctx;
+		OM_uint32 gssd_cred_verifier;
+		gssd_cred_id_t gssd_cl_cred_handle;
+
+		/*
+		 * If this is an initial call, we'll need to create the
+		 * wrapper struct that contains kernel state information, and
+		 * a reference to the handle from gssd.
+		 */
+		if (*context_handle == GSS_C_NO_CONTEXT) {
+			kctx = KGSS_ALLOC();
+			*context_handle = (gss_ctx_id_t)kctx;
+			kctx->gssd_ctx = (OM_uint32) GSS_C_NO_CONTEXT;
+		} else
+			kctx = (struct kgss_ctx *)*context_handle;
+
+		if (claimant_cred_handle != GSS_C_NO_CREDENTIAL) {
+			gssd_cred_verifier =
+				KCRED_TO_CREDV(claimant_cred_handle);
+			gssd_cl_cred_handle =
+				KCRED_TO_CRED(claimant_cred_handle);
+		} else
+			gssd_cl_cred_handle =
+					(gssd_cred_id_t)GSS_C_NO_CREDENTIAL;
+
+		err = kgss_init_sec_context_wrapped(minor_status,
+			gssd_cl_cred_handle,
+			gssd_cred_verifier, &kctx->gssd_ctx,
+			&kctx->gssd_ctx_verifier,
+			target_name, mech_type, req_flags, time_req,
+			input_chan_bindings, input_token, actual_mech_type,
+			output_token, ret_flags, time_rec, uid);
+
+		if (GSS_ERROR(err)) {
+			KGSS_FREE(kctx);
+			*context_handle = GSS_C_NO_CONTEXT;
+		}
+		return (err);
+}
+OM_uint32
+kgss_accept_sec_context_wrapped(minor_status,
+				context_handle,
+				gssd_context_verifier,
+				verifier_cred_handle,
+				gssd_cred_verifier,
+		input_token,
+		input_chan_bindings,
+		src_name,
+		mech_type,
+		output_token,
+		ret_flags,
+		time_rec,
+		delegated_cred_handle,
+		uid)
+	OM_uint32 *minor_status;
+	gssd_ctx_id_t *context_handle;
+	OM_uint32 *gssd_context_verifier;
+	gssd_cred_id_t verifier_cred_handle;
+	OM_uint32 gssd_cred_verifier;
+	gss_buffer_t input_token;
+	gss_channel_bindings_t input_chan_bindings;
+	gss_buffer_t src_name;
+	gss_OID *mech_type;
+	gss_buffer_t output_token;
+	int *ret_flags;
+	OM_uint32 *time_rec;
+	gss_cred_id_t *delegated_cred_handle;
+	uid_t uid;
+{
+	gss_accept_sec_context_arg arg;
+	gss_accept_sec_context_res res;
+	struct kgss_cred *kcred;
+
+	/* get the client handle to GSSD */
+	if ((clnt = getgssd_handle()) == NULL) {
+		clnt_pcreateerror(server);
+		return (GSS_S_FAILURE);
+	}
+
+	/* copy the procedure arguments into the rpc arg parameter */
+	arg.uid = (OM_uint32) uid;
+
+	arg.context_handle.GSS_CTX_ID_T_len =
+		*context_handle == (gssd_ctx_id_t)GSS_C_NO_CONTEXT ?
+			0 : (uint_t)sizeof (gssd_ctx_id_t);
+	arg.context_handle.GSS_CTX_ID_T_val =  (char *)context_handle;
+	arg.gssd_context_verifier =
+		*context_handle == (OM_uint32) GSS_C_NO_CONTEXT ?
+			0 : *gssd_context_verifier;
+
+	arg.verifier_cred_handle.GSS_CRED_ID_T_len =
+			verifier_cred_handle ==
+			(gssd_cred_id_t)GSS_C_NO_CREDENTIAL ?
+			0 : (uint_t)sizeof (gssd_cred_id_t);
+	arg.verifier_cred_handle.GSS_CRED_ID_T_val =
+						(char *)&verifier_cred_handle;
+	arg.gssd_cred_verifier = gssd_cred_verifier;
+
+	arg.input_token_buffer.GSS_BUFFER_T_len =
+			(uint_t)(input_token != GSS_C_NO_BUFFER ?
+					input_token->length : 0);
+	arg.input_token_buffer.GSS_BUFFER_T_val =
+			(char *)(input_token != GSS_C_NO_BUFFER ?
+					input_token->value : 0);
+
+	if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) {
+		arg.input_chan_bindings.present = YES;
+		arg.input_chan_bindings.initiator_addrtype =
+			input_chan_bindings->initiator_addrtype;
+		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len =
+			(uint_t)input_chan_bindings->initiator_address.length;
+		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val =
+			(void *) input_chan_bindings->initiator_address.value;
+		arg.input_chan_bindings.acceptor_addrtype =
+			input_chan_bindings->acceptor_addrtype;
+		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len =
+			(uint_t)input_chan_bindings->acceptor_address.length;
+		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val =
+			(void *) input_chan_bindings->acceptor_address.value;
+		arg.input_chan_bindings.application_data.GSS_BUFFER_T_len =
+			(uint_t)input_chan_bindings->application_data.length;
+		arg.input_chan_bindings.application_data.GSS_BUFFER_T_val =
+			(void *) input_chan_bindings->application_data.value;
+	} else {
+		arg.input_chan_bindings.present = NO;
+		arg.input_chan_bindings.initiator_addrtype = 0;
+		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = 0;
+		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = 0;
+		arg.input_chan_bindings.acceptor_addrtype = 0;
+		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = 0;
+		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = 0;
+		arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = 0;
+		arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = 0;
+	}
+
+	/* set the output parameters to empty values.... */
+	if (minor_status != NULL)
+		*minor_status = 0xffffffff;
+	if (src_name != NULL) {
+		src_name->length = 0;
+		src_name->value = NULL;
+	}
+	if (mech_type != NULL)
+		*mech_type = NULL;
+	if (output_token != NULL)
+		output_token->length = 0;
+	if (ret_flags != NULL)
+		*ret_flags = 0;
+	if (time_rec != NULL)
+		*time_rec = 0;
+	if (delegated_cred_handle != NULL)
+		*delegated_cred_handle = NULL;
+
+	/* call the remote procedure */
+	memset(&res, 0, sizeof (res));
+	if (gss_accept_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
+		return (GSS_S_FAILURE);
+	}
+
+
+	if (res.status == (OM_uint32) GSS_S_COMPLETE ||
+		res.status == (OM_uint32) GSS_S_CONTINUE_NEEDED) {
+		/*
+		 * when gss returns CONTINUE_NEEDED we can only
+		 * use the context, minor, and output token
+		 * parameters.
+		 */
+		/*LINTED*/
+		*context_handle = *((gssd_ctx_id_t *)
+			res.context_handle.GSS_CTX_ID_T_val);
+		*gssd_context_verifier = res.gssd_context_verifier;
+
+		if (output_token != NULL) {
+			output_token->length =
+				res.output_token.GSS_BUFFER_T_len;
+			output_token->value =
+				(void *) res.output_token.GSS_BUFFER_T_val;
+			res.output_token.GSS_BUFFER_T_val = 0;
+			res.output_token.GSS_BUFFER_T_len = 0;
+		}
+
+		if (minor_status != NULL)
+			*minor_status = res.minor_status;
+
+		/* the other parameters are ready on for COMPLETE */
+		if (res.status == GSS_S_COMPLETE)
+		{
+
+			/*
+			 *  The src_name is in external format.
+			 */
+			if (src_name != NULL) {
+			    src_name->length = res.src_name.GSS_BUFFER_T_len;
+			    src_name->value = res.src_name.GSS_BUFFER_T_val;
+			    res.src_name.GSS_BUFFER_T_val = NULL;
+			    res.src_name.GSS_BUFFER_T_len = 0;
+			}
+			/*
+			 * move mech type returned to mech_type
+			 * for gss_import_name_for_mech()
+			 */
+			if (mech_type != NULL) {
+				*mech_type =
+					(gss_OID) MALLOC(sizeof (gss_OID_desc));
+				(*mech_type)->length =
+					(OM_UINT32) res.mech_type.GSS_OID_len;
+				(*mech_type)->elements =
+					(void *) MALLOC((*mech_type)->length);
+				memcpy((*mech_type)->elements,
+					res.mech_type.GSS_OID_val,
+					(*mech_type)->length);
+			}
+
+			if (ret_flags != NULL)
+				*ret_flags = res.ret_flags;
+
+			if (time_rec != NULL)
+				*time_rec = res.time_rec;
+
+			if ((delegated_cred_handle != NULL) &&
+				(res.delegated_cred_handle.GSS_CRED_ID_T_len
+					!= 0)) {
+				kcred = KGSS_CRED_ALLOC();
+				/*LINTED*/
+				kcred->gssd_cred = *((gssd_cred_id_t *)
+				res.delegated_cred_handle.GSS_CRED_ID_T_val);
+				kcred->gssd_cred_verifier =
+					res.gssd_context_verifier;
+				*delegated_cred_handle = (gss_cred_id_t)kcred;
+			}
+		} /* res.status == GSS_S_COMPLETE */
+	} /* res.status == GSS_S_COMPLETE or GSS_CONTINUE_NEEDED */
+
+
+	/*
+	 * free the memory allocated for the results and return with the status
+	 * received in the rpc call
+	 */
+
+	clnt_freeres(clnt, xdr_gss_accept_sec_context_res, (caddr_t)&res);
+	return (res.status);
+}
+
+OM_uint32
+kgss_accept_sec_context(
+		OM_uint32 *minor_status,
+		gss_ctx_id_t *context_handle,
+		gss_cred_id_t verifier_cred_handle,
+		gss_buffer_t input_token,
+		gss_channel_bindings_t input_chan_bindings,
+		gss_buffer_t src_name,
+		gss_OID *mech_type,
+		gss_buffer_t output_token,
+		int *ret_flags,
+		OM_uint32 *time_rec,
+		gss_cred_id_t *delegated_cred_handle,
+		uid_t uid)
+{
+		OM_uint32 err;
+		struct kgss_ctx *kctx;
+		OM_uint32 gssd_cred_verifier;
+		gssd_cred_id_t gssd_ver_cred_handle;
+
+
+		if (*context_handle == GSS_C_NO_CONTEXT) {
+			kctx = KGSS_ALLOC();
+			*context_handle = (gss_ctx_id_t)kctx;
+		kctx->gssd_ctx = (gssd_ctx_id_t)GSS_C_NO_CONTEXT;
+		} else
+			kctx = (struct kgss_ctx *)*context_handle;
+
+	if (verifier_cred_handle != GSS_C_NO_CREDENTIAL) {
+			gssd_cred_verifier =
+				KCRED_TO_CREDV(verifier_cred_handle);
+			gssd_ver_cred_handle =
+				KCRED_TO_CRED(verifier_cred_handle);
+	} else
+		gssd_ver_cred_handle = (gssd_cred_id_t)GSS_C_NO_CREDENTIAL;
+
+		err = kgss_accept_sec_context_wrapped(minor_status,
+			&kctx->gssd_ctx,
+			&kctx->gssd_ctx_verifier, gssd_ver_cred_handle,
+			gssd_cred_verifier, input_token, input_chan_bindings,
+			src_name, mech_type, output_token, ret_flags,
+			time_rec, delegated_cred_handle, uid);
+
+	if (GSS_ERROR(err)) {
+		KGSS_FREE(kctx);
+		*context_handle = GSS_C_NO_CONTEXT;
+
+	}
+
+	return (err);
+}
+
+OM_uint32
+kgss_process_context_token(minor_status,
+			context_handle,
+			token_buffer,
+			uid)
+	OM_uint32 *minor_status;
+	gss_ctx_id_t context_handle;
+	gss_buffer_t token_buffer;
+	uid_t uid;
+{
+	OM_uint32 gssd_context_verifier;
+
+	gss_process_context_token_arg arg;
+	gss_process_context_token_res res;
+
+	gssd_context_verifier = KGSS_CTX_TO_GSSD_CTXV(context_handle);
+
+	/* get the client handle to GSSD */
+
+	if ((clnt = getgssd_handle()) == NULL) {
+		clnt_pcreateerror(server);
+		return (GSS_S_FAILURE);
+	}
+
+	/* copy the procedure arguments into the rpc arg parameter */
+	arg.uid = (OM_uint32) uid;
+
+	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gss_ctx_id_t);
+	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
+	arg.gssd_context_verifier = gssd_context_verifier;
+	arg.token_buffer.GSS_BUFFER_T_len = (uint_t)token_buffer;
+	arg.token_buffer.GSS_BUFFER_T_val = (char *)token_buffer->value;
+
+	/* call the remote procedure */
+
+	memset(&res, 0, sizeof (res));
+	if (gss_process_context_token_1(&arg, &res, clnt) != RPC_SUCCESS) {
+
+	/*
+	 * if the RPC call times out, null out all return arguments,
+	 * set minor_status to its maximum value, and return GSS_S_FAILURE
+	 */
+
+		if (minor_status != NULL)
+			*minor_status = 0xffffffff;
+
+		return (GSS_S_FAILURE);
+	}
+
+	/* copy the rpc results into the return arguments */
+
+	if (minor_status != NULL)
+		*minor_status = res.minor_status;
+
+	/* return with status returned in rpc call */
+
+	return (res.status);
+}
+
+OM_uint32
+kgss_delete_sec_context_wrapped(minor_status,
+			context_handle,
+			gssd_context_verifier,
+			output_token)
+	OM_uint32 *minor_status;
+	gssd_ctx_id_t *context_handle;
+	OM_uint32 gssd_context_verifier;
+	gss_buffer_t output_token;
+{
+	gss_delete_sec_context_arg arg;
+	gss_delete_sec_context_res res;
+
+
+	/* get the client handle to GSSD */
+	if ((clnt = getgssd_handle()) == NULL) {
+		clnt_pcreateerror(server);
+		return (GSS_S_FAILURE);
+	}
+
+	/* copy the procedure arguments into the rpc arg parameter */
+
+	arg.context_handle.GSS_CTX_ID_T_len =
+		*context_handle == (OM_uint32) GSS_C_NO_CONTEXT ? 0 :
+		(uint_t)sizeof (OM_uint32);
+	arg.context_handle.GSS_CTX_ID_T_val =  (char *)context_handle;
+
+	arg.gssd_context_verifier = gssd_context_verifier;
+
+	/* call the remote procedure */
+
+	memset(&res, 0, sizeof (res));
+	if (gss_delete_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
+
+		/*
+		 * if the RPC call times out, null out all return arguments,
+		 * set minor_status to its max value, and return GSS_S_FAILURE
+		 */
+
+		if (minor_status != NULL)
+			*minor_status = 0xffffffff;
+		if (context_handle != NULL)
+			*context_handle = NULL;
+		if (output_token != NULL)
+			output_token->length = 0;
+
+		return (GSS_S_FAILURE);
+	}
+
+	/* copy the rpc results into the return arguments */
+
+	if (minor_status != NULL)
+		*minor_status = res.minor_status;
+
+	if (res.context_handle.GSS_CTX_ID_T_len == 0)
+		*context_handle = NULL;
+	else
+		/*LINTED*/
+		*context_handle = *((gssd_ctx_id_t *)
+			res.context_handle.GSS_CTX_ID_T_val);
+
+	if (output_token != NULL) {
+		output_token->length = res.output_token.GSS_BUFFER_T_len;
+		output_token->value = res.output_token.GSS_BUFFER_T_val;
+		res.output_token.GSS_BUFFER_T_len = 0;
+		res.output_token.GSS_BUFFER_T_val = NULL;
+	}
+
+	/*
+	 * free the memory allocated for the results and return with the status
+	 * received in the rpc call
+	 */
+
+	clnt_freeres(clnt, xdr_gss_delete_sec_context_res, (caddr_t)&res);
+	return (res.status);
+}
+
+/*ARGSUSED*/
+OM_uint32
+kgss_delete_sec_context(
+		OM_uint32 *minor_status,
+		gss_ctx_id_t *context_handle,
+		gss_buffer_t output_token)
+{
+		OM_uint32 err;
+		struct kgss_ctx *kctx;
+
+		if (*context_handle == GSS_C_NO_CONTEXT) {
+			return (GSS_S_NO_CONTEXT);
+		} else
+			kctx = KCTX_TO_KGSS_CTX(*context_handle);
+
+		err = kgss_delete_sec_context_wrapped(minor_status,
+				&kctx->gssd_ctx, kctx->gssd_ctx_verifier,
+				output_token);
+
+		if (kctx->gssd_ctx != (gssd_ctx_id_t)GSS_C_NO_CONTEXT)
+			err = GSS_S_FAILURE;
+		else
+			err = GSS_S_COMPLETE;
+
+		KGSS_FREE(kctx);
+		*context_handle = GSS_C_NO_CONTEXT;
+		return (err);
+}
+
+/*ARGSUSED*/
+OM_uint32
+kgss_context_time(minor_status,
+		context_handle,
+		time_rec,
+		uid)
+	OM_uint32 *minor_status;
+	gss_ctx_id_t context_handle;
+	OM_uint32 *time_rec;
+	uid_t uid;
+{
+	return (GSS_S_FAILURE);
+}
+
+OM_uint32
+kgss_sign_wrapped(minor_status,
+		context_handle,
+		qop_req,
+		message_buffer,
+		msg_token,
+		gssd_context_verifier)
+	OM_uint32 *minor_status;
+	gssd_ctx_id_t context_handle;
+	OM_uint32 gssd_context_verifier;
+	int qop_req;
+	gss_buffer_t message_buffer;
+	gss_buffer_t msg_token;
+{
+
+	gss_sign_arg arg;
+	gss_sign_res res;
+
+	/* get the client handle to GSSD */
+
+	if ((clnt = getgssd_handle()) == NULL) {
+		clnt_pcreateerror(server);
+		return (GSS_S_FAILURE);
+	}
+
+	/* copy the procedure arguments into the rpc arg parameter */
+
+
+	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
+	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
+	arg.gssd_context_verifier = gssd_context_verifier;
+
+	arg.qop_req = qop_req;
+	arg.message_buffer.GSS_BUFFER_T_len = (uint_t)message_buffer->length;
+	arg.message_buffer.GSS_BUFFER_T_val = (char *)message_buffer->value;
+
+	/* call the remote procedure */
+
+	memset(&res, 0, sizeof (res));
+	if (gss_sign_1(&arg, &res, clnt) != RPC_SUCCESS) {
+
+	/*
+	 * if the RPC call times out, null out all return arguments,
+	 * set minor_status to its maximum value, and return GSS_S_FAILURE
+	 */
+
+		if (minor_status != NULL)
+			*minor_status = 0xffffffff;
+		if (msg_token != NULL)
+			msg_token->length = 0;
+
+		return (GSS_S_FAILURE);
+	}
+
+	/* copy the rpc results into the return arguments */
+
+	if (minor_status != NULL)
+		*minor_status = res.minor_status;
+
+	if (msg_token != NULL) {
+		msg_token->length = res.msg_token.GSS_BUFFER_T_len;
+		msg_token->value = (void *) MALLOC(msg_token->length);
+		memcpy(msg_token->value, res.msg_token.GSS_BUFFER_T_val,
+			msg_token->length);
+	}
+
+	/*
+	 * free the memory allocated for the results and return with the status
+	 * received in the rpc call
+	 */
+
+	clnt_freeres(clnt, xdr_gss_sign_res, (caddr_t)&res);
+	return (res.status);
+}
+
+OM_uint32
+kgss_sign(
+		OM_uint32 *minor_status,
+		gss_ctx_id_t context_handle,
+		int qop_req,
+		gss_buffer_t message_buffer,
+		gss_buffer_t msg_token)
+{
+		if (context_handle == GSS_C_NO_CONTEXT)
+			return (GSS_S_FAILURE);
+
+		return (KGSS_SIGN(minor_status,
+			context_handle, qop_req, message_buffer,
+			msg_token));
+}
+
+OM_uint32
+kgss_verify_wrapped(
+		minor_status,
+		context_handle,
+		message_buffer,
+		token_buffer,
+		qop_state,
+		gssd_context_verifier)
+	OM_uint32 *minor_status;
+	gssd_ctx_id_t context_handle;
+	OM_uint32 gssd_context_verifier;
+	gss_buffer_t message_buffer;
+	gss_buffer_t token_buffer;
+	int *qop_state;
+{
+	gss_verify_arg arg;
+	gss_verify_res res;
+
+/* get the client handle to GSSD */
+
+	if ((clnt = getgssd_handle()) == NULL) {
+		clnt_pcreateerror(server);
+		return (GSS_S_FAILURE);
+	}
+
+	/* copy the procedure arguments into the rpc arg parameter */
+
+	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
+	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
+
+	arg.gssd_context_verifier = gssd_context_verifier;
+
+	arg.message_buffer.GSS_BUFFER_T_len = (uint_t)message_buffer->length;
+	arg.message_buffer.GSS_BUFFER_T_val = (char *)message_buffer->value;
+
+	arg.token_buffer.GSS_BUFFER_T_len = (uint_t)token_buffer->length;
+	arg.token_buffer.GSS_BUFFER_T_val = (char *)token_buffer->value;
+
+	/* call the remote procedure */
+
+	memset(&res, 0, sizeof (res));
+	if (gss_verify_1(&arg, &res, clnt) != RPC_SUCCESS) {
+
+	/*
+	 * if the RPC call times out, null out all return arguments,
+	 * set minor_status to its maximum value, and return GSS_S_FAILURE
+	 */
+
+		if (minor_status != NULL)
+			*minor_status = 0xffffffff;
+		if (qop_state != NULL)
+			*qop_state = 0;
+
+		return (GSS_S_FAILURE);
+	}
+
+	/* copy the rpc results into the return arguments */
+
+	if (minor_status != NULL)
+		*minor_status = res.minor_status;
+
+	if (qop_state != NULL)
+		*qop_state = res.qop_state;
+
+	/* return with status returned in rpc call */
+
+	return (res.status);
+}
+
+OM_uint32
+kgss_verify(OM_uint32 *minor_status,
+	gss_ctx_id_t context_handle,
+	gss_buffer_t message_buffer,
+	gss_buffer_t token_buffer,
+	int *qop_state)
+{
+		if (context_handle == GSS_C_NO_CONTEXT)
+			return (GSS_S_FAILURE);
+
+		return (KGSS_VERIFY(minor_status, context_handle,
+			message_buffer,
+			token_buffer, qop_state));
+}
+
+
+/* EXPORT DELETE START */
+
+OM_uint32
+kgss_seal_wrapped(
+	minor_status,
+	context_handle,
+	conf_req_flag,
+	qop_req,
+	input_message_buffer,
+	conf_state,
+	output_message_buffer,
+	gssd_context_verifier)
+
+	OM_uint32 *minor_status;
+	gssd_ctx_id_t context_handle;
+	OM_uint32 gssd_context_verifier;
+	int conf_req_flag;
+	int qop_req;
+	gss_buffer_t input_message_buffer;
+	int *conf_state;
+	gss_buffer_t output_message_buffer;
+{
+	gss_seal_arg arg;
+	gss_seal_res res;
+
+	/* get the client handle to GSSD */
+
+	if ((clnt = getgssd_handle()) == NULL) {
+		clnt_pcreateerror(server);
+		return (GSS_S_FAILURE);
+	}
+
+	/* copy the procedure arguments into the rpc arg parameter */
+
+
+	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
+	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
+	arg.gssd_context_verifier = gssd_context_verifier;
+
+	arg.conf_req_flag = conf_req_flag;
+
+	arg.qop_req = qop_req;
+
+	arg.input_message_buffer.GSS_BUFFER_T_len =
+				(uint_t)input_message_buffer->length;
+
+	arg.input_message_buffer.GSS_BUFFER_T_val =
+				(char *)input_message_buffer->value;
+
+	/* call the remote procedure */
+
+	memset(&res, 0, sizeof (res));
+	if (gss_seal_1(&arg, &res, clnt) != RPC_SUCCESS) {
+
+	/*
+	 * if the RPC call times out, null out all return arguments,
+	 * set minor_status to its maximum value, and return GSS_S_FAILURE
+	 */
+
+		if (minor_status != NULL)
+			*minor_status = 0xffffffff;
+		if (conf_state != NULL)
+			*conf_state = 0;
+		if (output_message_buffer != NULL)
+			output_message_buffer->length = 0;
+
+		return (GSS_S_FAILURE);
+	}
+
+	/* copy the rpc results into the return arguments */
+
+	if (minor_status != NULL)
+		*minor_status = res.minor_status;
+
+	if (conf_state != NULL)
+		*conf_state = res.conf_state;
+
+	if (output_message_buffer != NULL) {
+		output_message_buffer->length =
+				res.output_message_buffer.GSS_BUFFER_T_len;
+
+		output_message_buffer->value =
+				(void *) MALLOC(output_message_buffer->length);
+		memcpy(output_message_buffer->value,
+			res.output_message_buffer.GSS_BUFFER_T_val,
+			output_message_buffer->length);
+	}
+
+	/*
+	 * free the memory allocated for the results and return with the status
+	 * received in the rpc call
+	 */
+
+	clnt_freeres(clnt, xdr_gss_seal_res, (caddr_t)&res);
+	return (res.status);
+}
+
+OM_uint32
+kgss_seal(OM_uint32 *minor_status,
+		gss_ctx_id_t context_handle,
+		int conf_req_flag,
+		int qop_req,
+		gss_buffer_t input_message_buffer,
+		int *conf_state,
+		gss_buffer_t output_message_buffer)
+
+{
+		if (context_handle == GSS_C_NO_CONTEXT)
+			return (GSS_S_FAILURE);
+
+		return (KGSS_SEAL(minor_status, context_handle,
+			conf_req_flag, qop_req,
+			input_message_buffer,
+			conf_state, output_message_buffer));
+}
+
+OM_uint32
+kgss_unseal_wrapped(minor_status,
+		context_handle,
+		input_message_buffer,
+		output_message_buffer,
+		conf_state,
+		qop_state,
+		gssd_context_verifier)
+	OM_uint32 *minor_status;
+	gssd_ctx_id_t context_handle;
+	OM_uint32 gssd_context_verifier;
+	gss_buffer_t input_message_buffer;
+	gss_buffer_t output_message_buffer;
+	int *conf_state;
+	int *qop_state;
+{
+	gss_unseal_arg arg;
+	gss_unseal_res res;
+
+	/* get the client handle to GSSD */
+
+	if ((clnt = getgssd_handle()) == NULL) {
+		clnt_pcreateerror(server);
+		return (GSS_S_FAILURE);
+	}
+
+	/* copy the procedure arguments into the rpc arg parameter */
+
+
+	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
+	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
+	arg.gssd_context_verifier = gssd_context_verifier;
+
+	arg.input_message_buffer.GSS_BUFFER_T_len =
+				(uint_t)input_message_buffer->length;
+
+	arg.input_message_buffer.GSS_BUFFER_T_val =
+				(char *)input_message_buffer->value;
+
+/* call the remote procedure */
+
+	memset(&res, 0, sizeof (res));
+	if (gss_unseal_1(&arg, &res, clnt) != RPC_SUCCESS) {
+
+	/*
+	 * if the RPC call times out, null out all return arguments,
+	 * set minor_status to its maximum value, and return GSS_S_FAILURE
+	 */
+
+		if (minor_status != NULL)
+			*minor_status = 0xffffffff;
+		if (output_message_buffer != NULL)
+			output_message_buffer->length = 0;
+		if (conf_state != NULL)
+			*conf_state = 0;
+		if (qop_state != NULL)
+			*qop_state = 0;
+
+		return (GSS_S_FAILURE);
+	}
+
+	/* copy the rpc results into the return arguments */
+
+	if (minor_status != NULL)
+		*minor_status = res.minor_status;
+
+	if (output_message_buffer != NULL) {
+		output_message_buffer->length =
+				res.output_message_buffer.GSS_BUFFER_T_len;
+
+		output_message_buffer->value =
+			(void *) MALLOC(output_message_buffer->length);
+		memcpy(output_message_buffer->value,
+			res.output_message_buffer.GSS_BUFFER_T_val,
+			output_message_buffer->length);
+	}
+
+	if (conf_state != NULL)
+		*conf_state = res.conf_state;
+
+	if (qop_state != NULL)
+		*qop_state = res.qop_state;
+
+	/*
+	 * free the memory allocated for the results and return with the status
+	 * received in the rpc call
+	 */
+
+	clnt_freeres(clnt, xdr_gss_unseal_res, (caddr_t)&res);
+	return (res.status);
+}
+
+OM_uint32
+kgss_unseal(OM_uint32 *minor_status,
+	gss_ctx_id_t context_handle,
+	gss_buffer_t input_message_buffer,
+	gss_buffer_t output_message_buffer,
+	int *conf_state,
+	int *qop_state)
+{
+		if (context_handle == GSS_C_NO_CONTEXT)
+			return (GSS_S_FAILURE);
+
+		return (KGSS_UNSEAL(minor_status, context_handle,
+			input_message_buffer,
+			output_message_buffer,
+			conf_state, qop_state));
+}
+
+/* EXPORT DELETE END */
+
+OM_uint32
+kgss_display_status(minor_status,
+		status_value,
+		status_type,
+		mech_type,
+		message_context,
+		status_string,
+		uid)
+	OM_uint32 *minor_status;
+	OM_uint32 status_value;
+	int status_type;
+	gss_OID mech_type;
+	int *message_context;
+	gss_buffer_t status_string;
+	uid_t uid;
+{
+	gss_display_status_arg arg;
+	gss_display_status_res res;
+
+	/* get the client handle to GSSD */
+
+	if ((clnt = getgssd_handle()) == NULL) {
+		clnt_pcreateerror(server);
+		return (GSS_S_FAILURE);
+	}
+
+	/* copy the procedure arguments into the rpc arg parameter */
+
+	arg.uid = (OM_uint32) uid;
+
+	arg.status_value = status_value;
+	arg.status_type = status_type;
+
+	arg.mech_type.GSS_OID_len = (uint_t)(mech_type != GSS_C_NULL_OID ?
+					mech_type->length : 0);
+	arg.mech_type.GSS_OID_val = (char *)(mech_type != GSS_C_NULL_OID ?
+					mech_type->elements : 0);
+
+	arg.message_context = *message_context;
+
+	/* call the remote procedure */
+
+	if (message_context != NULL)
+		*message_context = 0;
+	if (status_string != NULL) {
+		status_string->length = 0;
+		status_string->value = NULL;
+	}
+
+	memset(&res, 0, sizeof (res));
+	if (gss_display_status_1(&arg, &res, clnt) != RPC_SUCCESS) {
+
+	/*
+	 * if the RPC call times out, null out all return arguments,
+	 * set minor_status to its maximum value, and return GSS_S_FAILURE
+	 */
+
+		if (minor_status != NULL)
+			*minor_status = 0xffffffff;
+
+		return (GSS_S_FAILURE);
+	}
+
+
+	/* now process the results and pass them back to the caller */
+
+	if (res.status == GSS_S_COMPLETE) {
+		if (minor_status != NULL)
+			*minor_status = res.minor_status;
+		if (message_context != NULL)
+			*message_context = res.message_context;
+		if (status_string != NULL) {
+			status_string->length =
+				(size_t)res.status_string.GSS_BUFFER_T_len;
+			status_string->value =
+				(void *)MALLOC(status_string->length);
+			memcpy(status_string->value,
+				res.status_string.GSS_BUFFER_T_val,
+				status_string->length);
+		}
+	}
+
+	clnt_freeres(clnt, xdr_gss_display_status_res, (caddr_t)&res);
+	return (res.status);
+}
+
+/*ARGSUSED*/
+OM_uint32
+kgss_indicate_mechs(minor_status,
+		mech_set,
+		uid)
+	OM_uint32 *minor_status;
+	gss_OID_set *mech_set;
+	uid_t uid;
+{
+	void *arg;
+	gss_indicate_mechs_res res;
+	int i;
+
+	/* get the client handle to GSSD */
+
+	if ((clnt = getgssd_handle()) == NULL) {
+		clnt_pcreateerror(server);
+		return (GSS_S_FAILURE);
+	}
+
+	memset(&res, 0, sizeof (res));
+	if (gss_indicate_mechs_1(&arg, &res, clnt) != RPC_SUCCESS) {
+
+	/*
+	 * if the RPC call times out, null out all return arguments,
+	 * set minor_status to its maximum value, and return GSS_S_FAILURE
+	 */
+
+		if (minor_status != NULL)
+			*minor_status = 0xffffffff;
+		if (mech_set != NULL)
+			*mech_set = NULL;
+
+		return (GSS_S_FAILURE);
+	}
+
+	/* copy the rpc results into the return arguments */
+
+	if (minor_status != NULL)
+		*minor_status = res.minor_status;
+
+	if (mech_set != NULL) {
+		*mech_set = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
+		(*mech_set)->count = res.mech_set.GSS_OID_SET_len;
+		(*mech_set)->elements = (void *)
+			MALLOC ((*mech_set)->count * sizeof (gss_OID_desc));
+		for (i = 0; i < (*mech_set)->count; i++) {
+			(*mech_set)->elements[i].length =
+				res.mech_set.GSS_OID_SET_val[i].GSS_OID_len;
+			(*mech_set)->elements[i].elements = (void *)
+				MALLOC ((*mech_set)->elements[i].length);
+			memcpy ((*mech_set)->elements[i].elements,
+				res.mech_set.GSS_OID_SET_val[i].GSS_OID_val,
+				(*mech_set)->elements[i].length);
+		}
+	}
+
+	/*
+	 * free the memory allocated for the results and return with the status
+	 * received in the rpc call
+	 */
+
+	clnt_freeres(clnt, xdr_gss_indicate_mechs_res, (caddr_t)&res);
+	return (res.status);
+}
+
+
+OM_uint32
+kgss_inquire_cred_wrapped(minor_status,
+			cred_handle,
+			gssd_cred_verifier,
+			name,
+			lifetime,
+			cred_usage,
+			mechanisms,
+			uid)
+	OM_uint32 *minor_status;
+	gssd_cred_id_t cred_handle;
+	OM_uint32 gssd_cred_verifier;
+	gss_name_t *name;
+	OM_uint32 *lifetime;
+	int *cred_usage;
+	gss_OID_set *mechanisms;
+	uid_t uid;
+{
+	OM_uint32 minor_status_temp;
+	gss_buffer_desc external_name;
+	gss_OID name_type;
+	int i;
+
+	gss_inquire_cred_arg arg;
+	gss_inquire_cred_res res;
+
+	/* get the client handle to GSSD */
+
+	if ((clnt = getgssd_handle()) == NULL) {
+		clnt_pcreateerror(server);
+		return (GSS_S_FAILURE);
+	}
+
+
+	/* copy the procedure arguments into the rpc arg parameter */
+
+	arg.uid = (OM_uint32) uid;
+
+	arg.cred_handle.GSS_CRED_ID_T_len =
+			cred_handle == (gssd_cred_id_t)GSS_C_NO_CREDENTIAL ?
+			0 : (uint_t)sizeof (gssd_cred_id_t);
+	arg.cred_handle.GSS_CRED_ID_T_val = (char *)&cred_handle;
+	arg.gssd_cred_verifier = gssd_cred_verifier;
+
+	/* call the remote procedure */
+
+	memset(&res, 0, sizeof (res));
+	if (gss_inquire_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
+
+	/*
+	 * if the RPC call times out, null out all return arguments,
+	 * set minor_status to its maximum value, and return GSS_S_FAILURE
+	 */
+
+		if (minor_status != NULL)
+			*minor_status = 0xffffffff;
+		if (name != NULL)
+			*name = NULL;
+		if (lifetime != NULL)
+			*lifetime = 0;
+		if (cred_usage != NULL)
+			*cred_usage = 0;
+		if (mechanisms != NULL)
+			*mechanisms = NULL;
+
+		return (GSS_S_FAILURE);
+	}
+
+	/* copy the rpc results into the return arguments */
+
+	if (minor_status != NULL)
+		*minor_status = res.minor_status;
+
+	/* convert name from external to internal format */
+
+	if (name != NULL) {
+		external_name.length = res.name.GSS_BUFFER_T_len;
+		external_name.value = res.name.GSS_BUFFER_T_val;
+
+		/*
+		 * we have to allocate a name_type descriptor and
+		 * elements storage, since gss_import_name() only
+		 * stores a pointer to the name_type info in the
+		 * union_name struct
+		 */
+
+		name_type = (gss_OID) MALLOC(sizeof (gss_OID_desc));
+
+		name_type->length = res.name_type.GSS_OID_len;
+		name_type->elements = (void *) MALLOC(name_type->length);
+		memcpy(name_type->elements, res.name_type.GSS_OID_val,
+			name_type->length);
+
+		if (gss_import_name(&minor_status_temp, &external_name,
+			name_type, name) != GSS_S_COMPLETE) {
+
+			*minor_status = (OM_uint32) minor_status_temp;
+			gss_release_buffer(&minor_status_temp, &external_name);
+
+			clnt_freeres(clnt, xdr_gss_inquire_cred_res,
+							(caddr_t)&res);
+			return ((OM_uint32) GSS_S_FAILURE);
+		}
+	}
+
+	if (lifetime != NULL)
+		*lifetime = res.lifetime;
+
+	if (cred_usage != NULL)
+		*cred_usage = res.cred_usage;
+
+	if (mechanisms != NULL) {
+		*mechanisms =
+			(gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
+		if (res.mechanisms.GSS_OID_SET_len != 0) {
+			(*mechanisms)->count =
+					(int)res.mechanisms.GSS_OID_SET_len;
+			(*mechanisms)->elements = (gss_OID)
+				MALLOC(sizeof (gss_OID) * (*mechanisms)->count);
+
+			for (i = 0; i < (*mechanisms)->count; i++) {
+				(*mechanisms)->elements[i].length = (OM_uint32)
+				res.mechanisms.GSS_OID_SET_val[i].GSS_OID_len;
+				(*mechanisms)->elements[i].elements = (void *)
+				MALLOC((*mechanisms)->elements[i].length);
+				memcpy((*mechanisms)->elements[i].elements,
+				res.mechanisms.GSS_OID_SET_val[i].GSS_OID_val,
+				(*mechanisms)->elements[i].length);
+			}
+		} else
+			(*mechanisms)->count = 0;
+	}
+
+	/*
+	 * free the memory allocated for the results and return with the status
+	 * received in the rpc call
+	 */
+
+	clnt_freeres(clnt, xdr_gss_inquire_cred_res, (caddr_t)&res);
+	return (res.status);
+}
+
+
+OM_uint32
+kgss_inquire_cred(minor_status,
+			cred_handle,
+			name,
+			lifetime,
+			cred_usage,
+			mechanisms,
+			uid)
+	OM_uint32 *minor_status;
+	gss_cred_id_t cred_handle;
+	gss_name_t *name;
+	OM_uint32 *lifetime;
+	int *cred_usage;
+	gss_OID_set * mechanisms;
+	uid_t uid;
+{
+
+	OM_uint32 gssd_cred_verifier;
+	gssd_cred_id_t gssd_cred_handle;
+
+		gssd_cred_verifier = KCRED_TO_CREDV(cred_handle);
+		gssd_cred_handle = KCRED_TO_CRED(cred_handle);
+
+		return (kgss_inquire_cred_wrapped(minor_status,
+				gssd_cred_handle, gssd_cred_verifier,
+				name, lifetime, cred_usage, mechanisms, uid));
+}
+
+
+OM_uint32
+kgss_inquire_cred_by_mech_wrapped(minor_status,
+			cred_handle,
+			gssd_cred_verifier,
+			mech_type,
+			uid)
+	OM_uint32 *minor_status;
+	gssd_cred_id_t cred_handle;
+	OM_uint32 gssd_cred_verifier;
+	gss_OID mech_type;
+	uid_t uid;
+{
+	OM_uint32 minor_status_temp;
+
+	gss_inquire_cred_by_mech_arg arg;
+	gss_inquire_cred_by_mech_res res;
+
+	/* get the client handle to GSSD */
+
+	if ((clnt = getgssd_handle()) == NULL) {
+		clnt_pcreateerror(server);
+		return (GSS_S_FAILURE);
+	}
+
+
+	/* copy the procedure arguments into the rpc arg parameter */
+
+	arg.uid = (OM_uint32) uid;
+
+	arg.cred_handle.GSS_CRED_ID_T_len =
+			cred_handle == (gssd_cred_id_t)GSS_C_NO_CREDENTIAL ?
+			0 : (uint_t)sizeof (gssd_cred_id_t);
+	arg.cred_handle.GSS_CRED_ID_T_val = (char *)&cred_handle;
+	arg.gssd_cred_verifier = gssd_cred_verifier;
+
+	arg.mech_type.GSS_OID_len =
+		(uint_t)(mech_type != GSS_C_NULL_OID ?
+		mech_type->length : 0);
+	arg.mech_type.GSS_OID_val =
+		(char *)(mech_type != GSS_C_NULL_OID ?
+		mech_type->elements : 0);
+	/* call the remote procedure */
+
+	memset(&res, 0, sizeof (res));
+	if (gss_inquire_cred_by_mech_1(&arg, &res, clnt) != RPC_SUCCESS) {
+
+	/*
+	 * if the RPC call times out, null out all return arguments,
+	 * set minor_status to its maximum value, and return GSS_S_FAILURE
+	 */
+
+		if (minor_status != NULL)
+			*minor_status = 0xffffffff;
+		return (GSS_S_FAILURE);
+	}
+
+	/* copy the rpc results into the return arguments */
+
+	if (minor_status != NULL)
+		*minor_status = res.minor_status;
+
+	/* convert name from external to internal format */
+
+	/*
+	 * free the memory allocated for the results and return with the status
+	 * received in the rpc call
+	 */
+
+	clnt_freeres(clnt, xdr_gss_inquire_cred_by_mech_res, (caddr_t)&res);
+	return (res.status);
+}
+
+
+OM_uint32
+kgss_inquire_cred_by_mech(minor_status,
+			cred_handle,
+			mech_type,
+			uid)
+	OM_uint32 *minor_status;
+	gss_cred_id_t cred_handle;
+	gss_OID mech_type;
+	uid_t uid;
+{
+
+	OM_uint32 gssd_cred_verifier;
+	gssd_cred_id_t gssd_cred_handle;
+
+	gssd_cred_verifier = KCRED_TO_CREDV(cred_handle);
+	gssd_cred_handle = KCRED_TO_CRED(cred_handle);
+
+	return (kgss_inquire_cred_by_mech_wrapped(minor_status,
+			gssd_cred_handle, gssd_cred_verifier,
+			mech_type, uid));
+}
+
+OM_uint32
+kgsscred_expname_to_unix_cred(expName, uidOut, gidOut, gids, gidsLen, uid)
+	const gss_buffer_t expName;
+	uid_t *uidOut;
+	gid_t *gidOut;
+	gid_t *gids[];
+	int *gidsLen;
+	uid_t uid;
+{
+	gsscred_expname_to_unix_cred_arg args;
+	gsscred_expname_to_unix_cred_res res;
+
+	/* check input/output parameters */
+	if (expName == NULL || expName->value == NULL)
+		return (GSS_S_CALL_INACCESSIBLE_READ);
+
+	if (uidOut == NULL)
+		return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+	/* NULL out output parameters */
+	*uidOut = 0;
+	if (gidsLen)
+		*gidsLen = 0;
+
+	if (gids)
+		*gids = NULL;
+
+	/* get the client handle to gssd */
+	if ((clnt = getgssd_handle()) == NULL)
+	{
+		clnt_pcreateerror(server);
+		return (GSS_S_FAILURE);
+	}
+
+	/* copy the procedure arguments */
+	args.uid = uid;
+	args.expname.GSS_BUFFER_T_val = expName->value;
+	args.expname.GSS_BUFFER_T_len = expName->length;
+
+	/* null out the return buffer and call the remote proc */
+	memset(&res, 0, sizeof (res));
+
+	if (gsscred_expname_to_unix_cred_1(&args, &res, clnt) != RPC_SUCCESS)
+	{
+		return (GSS_S_FAILURE);
+	}
+
+	/* copy the results into the result parameters */
+	if (res.major == GSS_S_COMPLETE)
+	{
+		*uidOut = res.uid;
+		if (gidOut)
+			*gidOut = res.gid;
+		if (gids && gidsLen)
+		{
+			*gids = res.gids.GSSCRED_GIDS_val;
+			*gidsLen = res.gids.GSSCRED_GIDS_len;
+			res.gids.GSSCRED_GIDS_val = NULL;
+			res.gids.GSSCRED_GIDS_len = 0;
+		}
+	}
+
+	/* free RPC results */
+	clnt_freeres(clnt, xdr_gsscred_expname_to_unix_cred_res, (caddr_t)&res);
+
+	return (res.major);
+} /* kgsscred_expname_to_unix_cred */
+
+OM_uint32
+kgsscred_name_to_unix_cred(intName, mechType, uidOut, gidOut, gids,
+				gidsLen, uid)
+	const gss_name_t intName;
+	const gss_OID mechType;
+	uid_t *uidOut;
+	gid_t *gidOut;
+	gid_t *gids[];
+	int *gidsLen;
+	uid_t uid;
+{
+	gsscred_name_to_unix_cred_arg args;
+	gsscred_name_to_unix_cred_res res;
+	OM_uint32 major, minor;
+	gss_OID nameOid;
+	gss_buffer_desc flatName = GSS_C_EMPTY_BUFFER;
+
+
+	/* check the input/output parameters */
+	if (intName == NULL || mechType == NULL)
+		return (GSS_S_CALL_INACCESSIBLE_READ);
+
+	if (uidOut == NULL)
+		return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+	/* NULL out the output parameters */
+	*uidOut = 0;
+	if (gids)
+		*gids = NULL;
+
+	if (gidsLen)
+		*gidsLen = 0;
+
+	/* get the client handle to gssd */
+	if ((clnt = getgssd_handle()) == NULL)
+	{
+		clnt_pcreateerror(server);
+		return (GSS_S_FAILURE);
+	}
+
+	/* convert the name to flat representation */
+	if ((major = gss_display_name(&minor, intName, &flatName, &nameOid))
+			!= GSS_S_COMPLETE)
+	{
+		return (major);
+	}
+
+	/* set the rpc parameters */
+	args.uid = uid;
+	args.pname.GSS_BUFFER_T_len = flatName.length;
+	args.pname.GSS_BUFFER_T_val = flatName.value;
+	args.name_type.GSS_OID_len = nameOid->length;
+	args.name_type.GSS_OID_val = nameOid->elements;
+	args.mech_type.GSS_OID_len = mechType->length;
+	args.mech_type.GSS_OID_val = mechType->elements;
+
+	/* call the remote procedure */
+	memset(&res, 0, sizeof (res));
+	if (gsscred_name_to_unix_cred_1(&args, &res, clnt) != RPC_SUCCESS)
+	{
+		gss_release_buffer(&minor, &flatName);
+		return (GSS_S_FAILURE);
+	}
+
+	gss_release_buffer(&minor, &flatName);
+	/* copy the output parameters on output */
+	if (res.major == GSS_S_COMPLETE)
+	{
+		*uidOut = res.uid;
+		if (gidOut)
+			*gidOut = res.gid;
+		if (gids && gidsLen)
+		{
+			*gids = res.gids.GSSCRED_GIDS_val;
+			*gidsLen = res.gids.GSSCRED_GIDS_len;
+			res.gids.GSSCRED_GIDS_val = NULL;
+			res.gids.GSSCRED_GIDS_len = 0;
+		}
+	}
+
+	/* delete RPC allocated memory */
+	clnt_freeres(clnt, xdr_gsscred_name_to_unix_cred_res, (caddr_t)&res);
+
+	return (res.major);
+} /* kgsscred_name_to_unix_cred */
+
+OM_uint32
+kgss_get_group_info(puid, gidOut, gids, gidsLen, uid)
+	const uid_t puid;
+	gid_t *gidOut;
+	gid_t *gids[];
+	int *gidsLen;
+	uid_t uid;
+{
+	gss_get_group_info_arg args;
+	gss_get_group_info_res res;
+
+
+	/* check the output parameters */
+	if (gidOut == NULL || gids == NULL || gidsLen == NULL)
+		return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+	/* get the client GSSD handle */
+	if ((clnt = getgssd_handle()) == NULL)
+	{
+		clnt_pcreateerror(server);
+		return (GSS_S_FAILURE);
+	}
+
+	/* set the input parameters */
+	args.uid = uid;
+	args.puid = puid;
+
+
+	/* call the remote procedure */
+	memset(&res, 0, sizeof (res));
+	if (gss_get_group_info_1(&args, &res, clnt) != RPC_SUCCESS)
+	{
+		return (GSS_S_FAILURE);
+	}
+
+	/* copy the results */
+	if (res.major == GSS_S_COMPLETE)
+	{
+		*gidOut = res.gid;
+		*gids = res.gids.GSSCRED_GIDS_val;
+		*gidsLen = res.gids.GSSCRED_GIDS_len;
+		res.gids.GSSCRED_GIDS_val = NULL;
+		res.gids.GSSCRED_GIDS_len = 0;
+	}
+
+	/* nothing to free */
+
+	return (res.major);
+} /* kgss_get_group_info */
+
+OM_uint32
+kgss_export_sec_context_wrapped(minor_status,
+				context_handle,
+				output_token,
+				gssd_context_verifier)
+	OM_uint32 *minor_status;
+	gssd_ctx_id_t *context_handle;
+	gss_buffer_t output_token;
+	OM_uint32 gssd_context_verifier;
+{
+	CLIENT *clnt;
+	gss_export_sec_context_arg arg;
+	gss_export_sec_context_res res;
+
+
+/* get the client handle to GSSD */
+
+	if ((clnt = getgssd_handle()) == NULL) {
+		clnt_pcreateerror(server);
+		return (GSS_S_FAILURE);
+	}
+
+/* copy the procedure arguments into the rpc arg parameter */
+
+	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
+	arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle;
+	arg.gssd_context_verifier = gssd_context_verifier;
+
+/* call the remote procedure */
+
+	memset(&res, 0, sizeof (res));
+	if (gss_export_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
+
+/*
+ * if the RPC call times out, null out all return arguments, set minor_status
+ * to its maximum value, and return GSS_S_FAILURE
+ */
+
+		if (minor_status != NULL)
+			*minor_status = DEFAULT_MINOR_STAT;
+		if (context_handle != NULL)
+			*context_handle = NULL;
+		if (output_token != NULL)
+			output_token->length = 0;
+
+		return (GSS_S_FAILURE);
+	}
+
+/* copy the rpc results into the return arguments */
+
+	if (minor_status != NULL)
+		*minor_status = res.minor_status;
+
+	if (res.context_handle.GSS_CTX_ID_T_len == 0)
+		*context_handle = NULL;
+	else
+		*context_handle =
+		    *((gssd_ctx_id_t *)res.context_handle.GSS_CTX_ID_T_val);
+
+	if (output_token != NULL) {
+		output_token->length = res.output_token.GSS_BUFFER_T_len;
+		output_token->value =
+			(void *) MALLOC(output_token->length);
+		memcpy(output_token->value,
+			res.output_token.GSS_BUFFER_T_val,
+			output_token->length);
+	}
+
+/*
+ * free the memory allocated for the results and return with the status
+ * received in the rpc call
+ */
+
+	clnt_freeres(clnt, xdr_gss_export_sec_context_res, (caddr_t)&res);
+	return (res.status);
+
+}
+
+OM_uint32
+kgss_export_sec_context(minor_status,
+			context_handle,
+			output_token)
+	OM_uint32 *minor_status;
+	gss_ctx_id_t *context_handle;
+	gss_buffer_t output_token;
+{
+	OM_uint32 err;
+	struct kgss_ctx *kctx;
+
+	if (*context_handle == GSS_C_NO_CONTEXT) {
+		return (GSS_S_NO_CONTEXT);
+	} else
+		kctx = KCTX_TO_KGSS_CTX(*context_handle);
+
+	err = kgss_export_sec_context_wrapped(minor_status,
+		&kctx->gssd_ctx, output_token,
+		kctx->gssd_ctx_verifier);
+
+	if (GSS_ERROR(err))
+		return (err);
+	else {
+		KGSS_FREE(kctx);
+		*context_handle = GSS_C_NO_CONTEXT;
+		return (err);
+	}
+
+}
+
+OM_uint32
+kgss_import_sec_context_wrapped(minor_status,
+			input_token,
+			context_handle,
+			gssd_context_verifier)
+	OM_uint32 *minor_status;
+	gss_buffer_t input_token;
+	gss_ctx_id_t *context_handle;
+	OM_uint32 gssd_context_verifier;
+{
+	CLIENT *clnt;
+	gss_import_sec_context_arg arg;
+	gss_import_sec_context_res res;
+
+
+/* get the client handle to GSSD */
+
+	if ((clnt = getgssd_handle()) == NULL) {
+		clnt_pcreateerror(server);
+		return (GSS_S_FAILURE);
+	}
+
+/* copy the procedure arguments into the rpc arg parameter */
+	arg.input_token.GSS_BUFFER_T_len = (uint_t)
+		(input_token != GSS_C_NO_BUFFER ? input_token->length : 0);
+	arg.input_token.GSS_BUFFER_T_val = (char *)
+		(input_token != GSS_C_NO_BUFFER ? input_token->value : 0);
+	arg.gssd_context_verifier = gssd_context_verifier;
+
+
+/* call the remote procedure */
+
+	memset(&res, 0, sizeof (res));
+	if (gss_import_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
+
+/*
+ * if the RPC call times out, null out all return arguments, set minor_status
+ * to its maximum value, and return GSS_S_FAILURE
+ */
+
+		if (minor_status != NULL)
+			*minor_status = DEFAULT_MINOR_STAT;
+		if (context_handle != NULL)
+			*context_handle = NULL;
+
+		return (GSS_S_FAILURE);
+	}
+
+/* copy the rpc results into the return arguments */
+
+	if (minor_status != NULL)
+		*minor_status = res.minor_status;
+
+	if (res.context_handle.GSS_CTX_ID_T_len == 0)
+		*context_handle = NULL;
+	else
+		*context_handle =
+		    *((gss_ctx_id_t *)res.context_handle.GSS_CTX_ID_T_val);
+
+
+/*
+ * free the memory allocated for the results and return with the status
+ * received in the rpc call
+ */
+
+	clnt_freeres(clnt, xdr_gss_import_sec_context_res, (caddr_t)&res);
+	return (res.status);
+}
+
+OM_uint32
+kgss_import_sec_context(minor_status,
+			input_token,
+			context_handle)
+	OM_uint32 *minor_status;
+	gss_buffer_t input_token;
+	gss_ctx_id_t *context_handle;
+{
+	struct kgss_ctx *kctx;
+
+	if (*context_handle == GSS_C_NO_CONTEXT) {
+		kctx = KGSS_ALLOC();
+		*context_handle = (gss_ctx_id_t)kctx;
+		kctx->gssd_ctx = (OM_uint32) GSS_C_NO_CONTEXT;
+	} else
+		kctx = (struct kgss_ctx *)*context_handle;
+	return (kgss_import_sec_context_wrapped(minor_status,
+		input_token, &kctx->gssd_ctx,
+		KCTX_TO_CTXV(context_handle)));
+}
+
+#ifdef _KERNEL
+#include <sys/modctl.h>
+
+static void *gss_clnt = NULL;
+
+#ifdef DEBUG
+typedef struct {
+	char		*name;		/* just put something here */
+} gssd_devstate_t;
+
+
+static void *gssd_state;
+
+static int gssd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
+{
+	/*	 cmn_err(CE_NOTE, "In gssd_attach"); */
+	switch (cmd) {
+	case DDI_ATTACH:
+		if (ddi_create_minor_node(dip, "gssd", S_IFCHR, 0, "gssd", 0)
+			== DDI_FAILURE) {
+			ddi_remove_minor_node(dip, NULL);
+			return (DDI_FAILURE);
+		}
+		return (DDI_SUCCESS);
+
+	default:
+		return (DDI_FAILURE);
+	}
+}
+
+static int gssd_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd,
+		void *arg, void **result)
+{
+	dev_t dev;
+	int error;
+
+/*	 cmn_err(CE_NOTE, "In gssd_getinfo"); */
+
+	switch (infocmd) {
+	case DDI_INFO_DEVT2INSTANCE:
+		dev = (dev_t)arg;
+		*result = (void *) getminor(dev);
+		error = DDI_SUCCESS;
+		break;
+
+	case DDI_INFO_DEVT2DEVINFO:
+	/*	cmn_err(CE_NOTE, "getinfo wants devinfo"); */
+	default:
+		error = DDI_FAILURE;
+		break;
+	}
+	return (error);
+}
+
+static int gssd_identify(dev_info_t *dip)
+{
+	/*	 cmn_err(CE_NOTE, "in gssd_identify"); */
+	if (strcmp(ddi_get_name(dip), "gssd") == 0)
+		return (DDI_IDENTIFIED);
+	else
+		return (DDI_NOT_IDENTIFIED);
+}
+
+static int gssd_probe(dev_info_t *dip)
+{
+	/*	 cmn_err(CE_NOTE, "In gssd_probe"); */
+
+	return (DDI_PROBE_SUCCESS);
+}
+
+static int gssd_open(dev_t *devp, int flag, int otyp, cred_t *credp)
+{
+	/*	 cmn_err (CE_NOTE, "In gssd_open"); */
+	if (otyp != OTYP_CHR)
+		return (EINVAL);
+
+	gss_clnt = getgssd_handle();
+	return (0);
+}
+
+static int gssd_close(dev_t dev, int flag, int otyp, cred_t *credp)
+{
+	/*	 cmn_err(CE_NOTE, "In gssd_close"); */
+	killgssd_handle(gss_clnt);
+	return (0);
+}
+
+static int gssd_write(dev_t dev, struct uio *uiop, cred_t *credp)
+{
+	char buffer[1024];
+	int len;
+
+	/*	 cmn_err(CE_NOTE, "In gssd_write"); */
+	bzero(buffer, 1024);
+
+	uiomove(buffer, 1024, UIO_WRITE, uiop);
+	len = strlen(buffer);
+
+	if (buffer[len-1] == '\n')
+		buffer[--len] = '\0';
+
+	cmn_err(CE_NOTE, "Got command: (%d) \"%s\"", len, buffer);
+	do_gssdtest(buffer);
+	return (0);
+}
+
+static struct cb_ops gssd_cb_ops = {
+	gssd_open,		/* cb_open */
+	gssd_close,		/* cb_close */
+	nodev,			/* cb_strategy */
+	nodev,			/* cb_print */
+	nodev,			/* cb_dump */
+	nulldev,		/* cb_read */
+	gssd_write,		/* cb_write */
+	nodev,			/* cb_ioctl */
+	nodev,			/* cb_devmap */
+	nodev,			/* cb_mmap */
+	nodev,			/* cb_segmap */
+	nochpoll,		/* cb_chpoll */
+	ddi_prop_op,		/* cb_prop_op */
+	NULL,			/* cb_stream */
+	(int)(D_NEW|D_MP)	/* cb_flag */
+};
+
+static struct dev_ops gssd_ops = {
+	DEVO_REV,		/* devo_rev */
+	0,			/* devo_refcnt */
+	gssd_getinfo,		/* devo_getinfo */
+	gssd_identify,		/* devo_identify */
+	nulldev,		/* devo_probe */
+	gssd_attach,		/* devo_attach */
+	nulldev,		/* devo_detach */
+	nodev,			/* devo_reset */
+	&gssd_cb_ops,		/* devo_cb_ops */
+	(struct bus_ops *)NULL	/* devo_bus_ops */
+};
+
+extern struct mod_ops mod_driverops;
+
+static struct modldrv modlmisc = {
+	&mod_driverops,
+	"GSSD DRV Client Module",
+	&gssd_ops
+
+#else /* !DEBUG */
+
+static struct modlmisc modlmisc = {
+	&mod_miscops,
+	"GSSD Client Module"
+#endif /* DEBUG */
+};
+
+static struct modlinkage modlinkage = {
+	MODREV_1,
+	(void *)&modlmisc,
+	NULL
+};
+
+char _depends_on[] = "strmod/rpcmod misc/tlimod";
+
+_init(void)
+{
+	int status;
+
+	if ((status = ddi_soft_state_init(&gssd_state,
+			sizeof (gssd_devstate_t), 1)) != 0)
+		return (status);
+
+	if ((status = mod_install((struct modlinkage *)&modlinkage)) != 0)
+		ddi_soft_state_fini(&gssd_state);
+
+	cmn_err(CE_NOTE, "gssd: I'm in the kernel: %d.", status);
+	return (status);
+}
+
+_fini()
+{
+	int status;
+
+	killgssd_handle(gss_clnt);
+	cmn_err(CE_NOTE, "gssd: Handle destroyed.. leaving module.");
+
+	if ((status = mod_remove(&modlinkage)) != 0)
+		return (status);
+
+	ddi_soft_state_fini(&gssd_state);
+	return (status);
+}
+
+_info(modinfop)
+struct modinfo *modinfop;
+{
+	return (mod_info(&modlinkage, modinfop));
+}
+
+#endif