xref: /illumos-gate/usr/src/cmd/gss/gssd/gssd_clnt_stubs.c (revision d4f95bf4d6ec7ef0f01e5ddf22813ac641edf019)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  *  GSSAPI library stub module for gssd.
28  */
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <mechglueP.h>
33 #include "gssd.h"
34 #include <rpc/rpc.h>
35 
36 #ifdef	_KERNEL
37 #define	MALLOC(n) kmem_alloc((n), KM_SLEEP)
38 #define	FREE(x, n) kmem_free((x), (n))
39 #define	memcpy(dst, src, n) bcopy((src), (dst), (n))
40 #define	clnt_pcreateerror(srv) printf("Cannot connect to server on %s\n", srv)
41 
42 #ifdef	DEBUG
43 #ifndef	_SYS_CMN_ERR_H
44 #define	_SYS_CMN_ERR_H
45 #define	CE_NOTE 1
46 #endif
47 #include <sys/types.h>
48 #include <sys/devops.h>
49 #include <sys/open.h>
50 #include <sys/stat.h>
51 #include <sys/conf.h>
52 #include <sys/ddi.h>
53 #include <sys/sunddi.h>
54 #include <sys/uio.h>
55 #endif /* DEBUG */
56 
57 #else /* !_KERNEL */
58 #define	MALLOC(n) malloc(n)
59 #define	FREE(x, n) free(x)
60 #endif /* _KERNEL */
61 #define	DEFAULT_MINOR_STAT	((OM_uint32) ~0)
62 
63 CLIENT  *clnt, *getgssd_handle();
64 char *server = "localhost";
65 
66 OM_uint32
67 kgss_acquire_cred_wrapped(minor_status,
68 			desired_name,
69 			time_req,
70 			desired_mechs,
71 			cred_usage,
72 			output_cred_handle,
73 			actual_mechs,
74 			time_rec,
75 			uid,
76 			gssd_cred_verifier)
77 	OM_uint32 *minor_status;
78 	gss_name_t desired_name;
79 	OM_uint32 time_req;
80 	gss_OID_set desired_mechs;
81 	int cred_usage;
82 	gssd_cred_id_t *output_cred_handle;
83 	gss_OID_set *actual_mechs;
84 	OM_uint32 *time_rec;
85 	uid_t uid;
86 	OM_uint32 *gssd_cred_verifier;
87 {
88 	OM_uint32 minor_status_temp;
89 	gss_buffer_desc	external_name;
90 	gss_OID name_type;
91 	int i;
92 
93 	gss_acquire_cred_arg arg;
94 	gss_acquire_cred_res res;
95 
96 	/* get the client handle to GSSD */
97 
98 	if ((clnt = getgssd_handle()) == NULL) {
99 		clnt_pcreateerror(server);
100 		return (GSS_S_FAILURE);
101 	}
102 
103 	/* convert the desired name from internal to external format */
104 
105 	if (gss_display_name(&minor_status_temp, desired_name, &external_name,
106 				&name_type) != GSS_S_COMPLETE) {
107 
108 			*minor_status = (OM_uint32) minor_status_temp;
109 			gss_release_buffer(&minor_status_temp, &external_name);
110 		return ((OM_uint32) GSS_S_FAILURE);
111 	}
112 
113 
114 	/* copy the procedure arguments into the rpc arg parameter */
115 
116 	arg.uid = (OM_uint32)uid;
117 
118 	arg.desired_name.GSS_BUFFER_T_len = (uint_t)external_name.length;
119 	arg.desired_name.GSS_BUFFER_T_val = (char *)external_name.value;
120 
121 	arg.name_type.GSS_OID_len =
122 		name_type == GSS_C_NULL_OID ?
123 			0 : (uint_t)name_type->length;
124 
125 	arg.name_type.GSS_OID_val =
126 		name_type == GSS_C_NULL_OID ?
127 			(char *)NULL : (char *)name_type->elements;
128 
129 	arg.time_req = time_req;
130 
131 	if (desired_mechs != GSS_C_NULL_OID_SET) {
132 		arg.desired_mechs.GSS_OID_SET_len =
133 			(uint_t)desired_mechs->count;
134 		arg.desired_mechs.GSS_OID_SET_val = (GSS_OID *)
135 			MALLOC(sizeof (GSS_OID) * desired_mechs->count);
136 
137 		for (i = 0; i < desired_mechs->count; i++) {
138 			arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_len =
139 				(uint_t)desired_mechs->elements[i].length;
140 			arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val =
141 				(char *)
142 				MALLOC(desired_mechs->elements[i].length);
143 			memcpy(arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val,
144 				desired_mechs->elements[i].elements,
145 				desired_mechs->elements[i].length);
146 		}
147 	} else
148 		arg.desired_mechs.GSS_OID_SET_len = 0;
149 
150 	arg.cred_usage = cred_usage;
151 
152 	/* call the remote procedure */
153 
154 	memset(&res, 0, sizeof (res));
155 	if (gss_acquire_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
156 
157 	/*
158 	 * if the RPC call times out, null out all return arguments,
159 	 * set minor_status to its maximum value, and return GSS_S_FAILURE
160 	 */
161 
162 		if (minor_status != NULL)
163 			*minor_status = DEFAULT_MINOR_STAT;
164 		if (output_cred_handle != NULL)
165 			*output_cred_handle = NULL;
166 		if (actual_mechs != NULL)
167 			*actual_mechs = NULL;
168 		if (time_rec != NULL)
169 			*time_rec = 0;
170 
171 		return (GSS_S_FAILURE);
172 	}
173 
174 	/* free the allocated memory for the flattened name and desire_mechs */
175 
176 	gss_release_buffer(&minor_status_temp, &external_name);
177 	for (i = 0; i < desired_mechs->count; i++)
178 		FREE(arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val,
179 			arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_len);
180 	FREE(arg.desired_mechs.GSS_OID_SET_val,
181 		arg.desired_mechs.GSS_OID_SET_len * sizeof (GSS_OID));
182 
183 	/* copy the rpc results into the return arguments */
184 
185 	if (minor_status != NULL)
186 		*minor_status = res.minor_status;
187 
188 	if (output_cred_handle != NULL) {
189 		 *output_cred_handle =
190 		/*LINTED*/
191 		*((gssd_cred_id_t *)res.output_cred_handle.GSS_CRED_ID_T_val);
192 		 *gssd_cred_verifier = res.gssd_cred_verifier;
193 	}
194 
195 	if (res.status == GSS_S_COMPLETE &&
196 		res.actual_mechs.GSS_OID_SET_len != 0 &&
197 		actual_mechs != NULL) {
198 		*actual_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
199 		(*actual_mechs)->count =
200 			(int)res.actual_mechs.GSS_OID_SET_len;
201 		(*actual_mechs)->elements = (gss_OID)
202 			MALLOC(sizeof (gss_OID_desc) * (*actual_mechs)->count);
203 
204 		for (i = 0; i < (*actual_mechs)->count; i++) {
205 			(*actual_mechs)->elements[i].length = (OM_uint32)
206 			res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_len;
207 			(*actual_mechs)->elements[i].elements =
208 			(void *) MALLOC((*actual_mechs)->elements[i].length);
209 			memcpy((*actual_mechs)->elements[i].elements,
210 			res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_val,
211 			(*actual_mechs)->elements[i].length);
212 		}
213 	} else {
214 		if (res.status == GSS_S_COMPLETE && actual_mechs != NULL)
215 			(*actual_mechs)->count = 0;
216 	}
217 
218 	if (time_rec != NULL)
219 		*time_rec = res.time_rec;
220 
221 	/*
222 	 * free the memory allocated for the results and return with the status
223 	 * received in the rpc call
224 	 */
225 
226 	clnt_freeres(clnt, xdr_gss_acquire_cred_res, (caddr_t)&res);
227 	return (res.status);
228 }
229 
230 OM_uint32
231 kgss_acquire_cred(minor_status,
232 		desired_name,
233 		time_req,
234 		desired_mechs,
235 		cred_usage,
236 		output_cred_handle,
237 		actual_mechs,
238 		time_rec,
239 		uid)
240 	OM_uint32 *minor_status;
241 	gss_name_t desired_name;
242 	OM_uint32 time_req;
243 	gss_OID_set desired_mechs;
244 	int cred_usage;
245 	gss_cred_id_t *output_cred_handle;
246 	gss_OID_set *actual_mechs;
247 	OM_uint32 *time_rec;
248 	uid_t uid;
249 {
250 
251 		OM_uint32	err;
252 		struct kgss_cred *kcred;
253 
254 		kcred = KGSS_CRED_ALLOC();
255 		*output_cred_handle = (gss_cred_id_t)kcred;
256 		err = kgss_acquire_cred_wrapped(minor_status,
257 					desired_name, time_req,
258 					desired_mechs, cred_usage,
259 					&kcred->gssd_cred, actual_mechs,
260 					time_rec, uid,
261 					&kcred->gssd_cred_verifier);
262 		if (GSS_ERROR(err)) {
263 			KGSS_CRED_FREE(kcred);
264 			*output_cred_handle = GSS_C_NO_CREDENTIAL;
265 		}
266 		return (err);
267 }
268 
269 OM_uint32
270 kgss_add_cred_wrapped(minor_status,
271 			input_cred_handle,
272 			gssd_cred_verifier,
273 			desired_name,
274 			desired_mech_type,
275 			cred_usage,
276 			initiator_time_req,
277 			acceptor_time_req,
278 			actual_mechs,
279 			initiator_time_rec,
280 			acceptor_time_rec,
281 			uid)
282 	OM_uint32 *minor_status;
283 	gssd_cred_id_t input_cred_handle;
284 	OM_uint32 gssd_cred_verifier;
285 	gss_name_t desired_name;
286 	gss_OID desired_mech_type;
287 	int cred_usage;
288 	int initiator_time_req;
289 	int acceptor_time_req;
290 	gss_OID_set *actual_mechs;
291 	OM_uint32 *initiator_time_rec;
292 	OM_uint32 *acceptor_time_rec;
293 	uid_t uid;
294 {
295 	CLIENT *clnt;
296 
297 	OM_uint32 	minor_status_temp;
298 	gss_buffer_desc	external_name;
299 	gss_OID		name_type;
300 	int		i;
301 
302 	gss_add_cred_arg arg;
303 	gss_add_cred_res res;
304 
305 	/* get the client handle to GSSD */
306 
307 	if ((clnt = getgssd_handle()) == NULL) {
308 		clnt_pcreateerror(server);
309 		return (GSS_S_FAILURE);
310 	}
311 
312 
313 	/* convert the desired name from internal to external format */
314 
315 	if (gss_display_name(&minor_status_temp, desired_name, &external_name,
316 				&name_type) != GSS_S_COMPLETE) {
317 
318 		*minor_status = (OM_uint32) minor_status_temp;
319 		(void) gss_release_buffer(&minor_status_temp, &external_name);
320 		clnt_pcreateerror(server);
321 		return ((OM_uint32) GSS_S_FAILURE);
322 	}
323 
324 
325 	/* copy the procedure arguments into the rpc arg parameter */
326 
327 	arg.uid = (OM_uint32) uid;
328 	arg.input_cred_handle.GSS_CRED_ID_T_len =
329 			input_cred_handle == GSSD_NO_CREDENTIAL ?
330 			0 : (uint_t)sizeof (gssd_cred_id_t);
331 	arg.input_cred_handle.GSS_CRED_ID_T_val =
332 						(char *)&input_cred_handle;
333 	arg.gssd_cred_verifier = gssd_cred_verifier;
334 	arg.desired_name.GSS_BUFFER_T_len = (uint_t)external_name.length;
335 	arg.desired_name.GSS_BUFFER_T_val = (char *)external_name.value;
336 	arg.name_type.GSS_OID_len =
337 		name_type == GSS_C_NULL_OID ?
338 			0 : (uint_t)name_type->length;
339 	arg.name_type.GSS_OID_val =
340 		name_type == GSS_C_NULL_OID ?
341 			(char *)NULL : (char *)name_type->elements;
342 
343 	arg.desired_mech_type.GSS_OID_len =
344 		(uint_t)(desired_mech_type != GSS_C_NULL_OID ?
345 		desired_mech_type->length : 0);
346 	arg.desired_mech_type.GSS_OID_val =
347 		(char *)(desired_mech_type != GSS_C_NULL_OID ?
348 		desired_mech_type->elements : 0);
349 	arg.cred_usage = cred_usage;
350 	arg.initiator_time_req = initiator_time_req;
351 	arg.acceptor_time_req = acceptor_time_req;
352 
353 	/* call the remote procedure */
354 
355 	bzero((caddr_t)&res, sizeof (res));
356 	if (gss_add_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
357 
358 		/*
359 		 * if the RPC call times out, null out all return arguments,
360 		 * set minor_status to its maximum value, and return
361 		 * GSS_S_FAILURE
362 		 */
363 
364 		if (minor_status != NULL)
365 			*minor_status = DEFAULT_MINOR_STAT;
366 		if (actual_mechs != NULL)
367 			*actual_mechs = NULL;
368 		if (initiator_time_rec != NULL)
369 			*initiator_time_rec = 0;
370 		if (acceptor_time_rec != NULL)
371 			*acceptor_time_rec = 0;
372 		return (GSS_S_FAILURE);
373 	}
374 
375 	/* free the allocated memory for the flattened name */
376 
377 	(void) gss_release_buffer(&minor_status_temp, &external_name);
378 
379 	/* copy the rpc results into the return arguments */
380 
381 	if (minor_status != NULL)
382 		*minor_status = res.minor_status;
383 
384 	if (res.status == GSS_S_COMPLETE &&
385 		res.actual_mechs.GSS_OID_SET_len != 0 &&
386 		actual_mechs != NULL) {
387 		*actual_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
388 		(*actual_mechs)->count =
389 					(int)res.actual_mechs.GSS_OID_SET_len;
390 		(*actual_mechs)->elements = (gss_OID)
391 			MALLOC(sizeof (gss_OID_desc) * (*actual_mechs)->count);
392 
393 		for (i = 0; i < (*actual_mechs)->count; i++) {
394 		    (*actual_mechs)->elements[i].length = (OM_uint32)
395 			res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_len;
396 		    (*actual_mechs)->elements[i].elements =
397 			(void *) MALLOC((*actual_mechs)->elements[i].length);
398 		    memcpy((*actual_mechs)->elements[i].elements,
399 			res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_val,
400 			(*actual_mechs)->elements[i].length);
401 		}
402 	} else {
403 		if (res.status == GSS_S_COMPLETE &&
404 			actual_mechs != NULL)
405 			(*actual_mechs)->count = 0;
406 	}
407 	if (initiator_time_rec != NULL)
408 		*initiator_time_rec = res.initiator_time_rec;
409 	if (acceptor_time_rec != NULL)
410 		*acceptor_time_rec = res.acceptor_time_rec;
411 
412 	/*
413 	 * free the memory allocated for the results and return with the status
414 	 * received in the rpc call
415 	 */
416 
417 	clnt_freeres(clnt, xdr_gss_add_cred_res, (caddr_t)&res);
418 	return (res.status);
419 
420 }
421 
422 OM_uint32
423 kgss_add_cred(minor_status,
424 			input_cred_handle,
425 			desired_name,
426 			desired_mech_type,
427 			cred_usage,
428 			initiator_time_req,
429 			acceptor_time_req,
430 			actual_mechs,
431 			initiator_time_rec,
432 			acceptor_time_rec,
433 			uid)
434 	OM_uint32 *minor_status;
435 	gss_cred_id_t input_cred_handle;
436 	gss_name_t desired_name;
437 	gss_OID desired_mech_type;
438 	int cred_usage;
439 	int initiator_time_req;
440 	int acceptor_time_req;
441 	gss_OID_set *actual_mechs;
442 	OM_uint32 *initiator_time_rec;
443 	OM_uint32 *acceptor_time_rec;
444 	uid_t uid;
445 {
446 
447 	OM_uint32	err;
448 	OM_uint32 gssd_cred_verifier;
449 	gssd_cred_id_t gssd_input_cred_handle;
450 
451 
452 	if (input_cred_handle != GSS_C_NO_CREDENTIAL) {
453 		gssd_cred_verifier = KCRED_TO_CREDV(input_cred_handle);
454 		gssd_input_cred_handle = KCRED_TO_CRED(input_cred_handle);
455 	} else
456 		gssd_input_cred_handle = GSSD_NO_CREDENTIAL;
457 
458 	err = kgss_add_cred_wrapped(minor_status, gssd_input_cred_handle,
459 			gssd_cred_verifier, desired_name, desired_mech_type,
460 			cred_usage, initiator_time_req, acceptor_time_req,
461 			actual_mechs, initiator_time_rec,
462 			acceptor_time_rec, uid);
463 	return (err);
464 }
465 
466 OM_uint32
467 kgss_release_cred_wrapped(minor_status,
468 		cred_handle,
469 		uid,
470 		gssd_cred_verifier)
471 OM_uint32 *minor_status;
472 gssd_cred_id_t *cred_handle;
473 uid_t uid;
474 OM_uint32 gssd_cred_verifier;
475 {
476 
477 	gss_release_cred_arg arg;
478 	gss_release_cred_res res;
479 
480 
481 	/* get the client handle to GSSD */
482 	if ((clnt = getgssd_handle()) == NULL) {
483 		clnt_pcreateerror(server);
484 		return (GSS_S_FAILURE);
485 	}
486 
487 	/* copy the procedure arguments into the rpc arg parameter */
488 
489 	arg.uid = (OM_uint32) uid;
490 	arg.gssd_cred_verifier = gssd_cred_verifier;
491 
492 	if (cred_handle != NULL) {
493 		arg.cred_handle.GSS_CRED_ID_T_len =
494 			(uint_t)sizeof (gssd_cred_id_t);
495 		arg.cred_handle.GSS_CRED_ID_T_val = (char *)cred_handle;
496 	} else
497 		arg.cred_handle.GSS_CRED_ID_T_len = 0;
498 
499 	/* call the remote procedure */
500 
501 	memset(&res, 0, sizeof (res));
502 	if (gss_release_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
503 
504 		/*
505 		 * if the RPC call times out, null out all return arguments,
506 		 * set minor_status to its max value, and return GSS_S_FAILURE
507 		 */
508 
509 		if (minor_status != NULL)
510 			*minor_status = DEFAULT_MINOR_STAT;
511 		if (cred_handle != NULL)
512 			*cred_handle = NULL;
513 
514 		return (GSS_S_FAILURE);
515 	}
516 
517 	/* if the release succeeded, null out the cred_handle */
518 	if (res.status == GSS_S_COMPLETE && cred_handle != NULL)
519 		*cred_handle = NULL;
520 
521 	/* copy the rpc results into the return arguments */
522 	if (minor_status != NULL)
523 		*minor_status = res.minor_status;
524 
525 	/* return with status returned in rpc call */
526 	return (res.status);
527 }
528 
529 OM_uint32
530 kgss_release_cred(minor_status,
531 			cred_handle,
532 			uid)
533 	OM_uint32 *minor_status;
534 	gss_cred_id_t *cred_handle;
535 	uid_t uid;
536 
537 {
538 
539 		OM_uint32	err;
540 		struct kgss_cred *kcred;
541 
542 		if (*cred_handle == GSS_C_NO_CREDENTIAL)
543 			return (GSS_S_COMPLETE);
544 		else
545 			kcred = KCRED_TO_KGSS_CRED(*cred_handle);
546 
547 		err = kgss_release_cred_wrapped(minor_status, &kcred->gssd_cred,
548 			uid, kcred->gssd_cred_verifier);
549 		KGSS_CRED_FREE(kcred);
550 		*cred_handle = GSS_C_NO_CREDENTIAL;
551 		return (err);
552 }
553 
554 OM_uint32
555 kgss_init_sec_context_wrapped(minor_status,
556 			claimant_cred_handle,
557 			gssd_cred_verifier,
558 			context_handle,
559 			gssd_context_verifier,
560 		target_name,
561 		mech_type,
562 		req_flags,
563 		time_req,
564 		input_chan_bindings,
565 		input_token,
566 		actual_mech_type,
567 		output_token,
568 		ret_flags,
569 		time_rec,
570 		uid)
571 	OM_uint32 *minor_status;
572 	gssd_cred_id_t claimant_cred_handle;
573 	OM_uint32 gssd_cred_verifier;
574 	OM_uint32 *context_handle;
575 	OM_uint32 *gssd_context_verifier;
576 	gss_name_t target_name;
577 	gss_OID mech_type;
578 	int req_flags;
579 	OM_uint32 time_req;
580 	gss_channel_bindings_t input_chan_bindings;
581 	gss_buffer_t input_token;
582 	gss_OID *actual_mech_type;
583 	gss_buffer_t output_token;
584 	int *ret_flags;
585 	OM_uint32 *time_rec;
586 	uid_t uid;
587 {
588 	OM_uint32 minor_status_temp;
589 	gss_buffer_desc external_name;
590 	gss_OID name_type;
591 	gss_init_sec_context_arg arg;
592 	gss_init_sec_context_res res;
593 
594 	/* get the client handle to GSSD */
595 
596 	if ((clnt = getgssd_handle()) == NULL) {
597 		clnt_pcreateerror(server);
598 		return (GSS_S_FAILURE);
599 	}
600 
601 	/* convert the target name from internal to external format */
602 
603 	if (gss_display_name(&minor_status_temp, target_name,
604 			&external_name, &name_type) != GSS_S_COMPLETE) {
605 
606 		*minor_status = (OM_uint32) minor_status_temp;
607 		return ((OM_uint32) GSS_S_FAILURE);
608 	}
609 
610 
611 /* copy the procedure arguments into the rpc arg parameter */
612 
613 	arg.uid = (OM_uint32) uid;
614 
615 	arg.context_handle.GSS_CTX_ID_T_len =
616 		*context_handle == (OM_uint32) GSS_C_NO_CONTEXT ? 0 :
617 		(uint_t)sizeof (OM_uint32);
618 	arg.context_handle.GSS_CTX_ID_T_val =  (char *)context_handle;
619 	arg.gssd_context_verifier = *gssd_context_verifier;
620 
621 	arg.claimant_cred_handle.GSS_CRED_ID_T_len =
622 		claimant_cred_handle == GSSD_NO_CREDENTIAL ?
623 		0 : (uint_t)sizeof (gssd_cred_id_t);
624 	arg.claimant_cred_handle.GSS_CRED_ID_T_val =
625 		(char *)&claimant_cred_handle;
626 	arg.gssd_cred_verifier =  gssd_cred_verifier;
627 
628 	arg.target_name.GSS_BUFFER_T_len = (uint_t)external_name.length;
629 	arg.target_name.GSS_BUFFER_T_val = (char *)external_name.value;
630 
631 	arg.name_type.GSS_OID_len =
632 		name_type == GSS_C_NULL_OID ?
633 		0 : (uint_t)name_type->length;
634 
635 	arg.name_type.GSS_OID_val =
636 		name_type == GSS_C_NULL_OID ?
637 		(char *)NULL : (char *)name_type->elements;
638 
639 	arg.mech_type.GSS_OID_len = (uint_t)(mech_type != GSS_C_NULL_OID ?
640 				mech_type->length : 0);
641 	arg.mech_type.GSS_OID_val = (char *)(mech_type != GSS_C_NULL_OID ?
642 				mech_type->elements : 0);
643 
644 	arg.req_flags = req_flags;
645 
646 	arg.time_req = time_req;
647 
648 	if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) {
649 		arg.input_chan_bindings.present = YES;
650 		arg.input_chan_bindings.initiator_addrtype =
651 			input_chan_bindings->initiator_addrtype;
652 		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len =
653 			(uint_t)input_chan_bindings->initiator_address.length;
654 		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val =
655 			(void *) input_chan_bindings->initiator_address.value;
656 		arg.input_chan_bindings.acceptor_addrtype =
657 			input_chan_bindings->acceptor_addrtype;
658 		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len =
659 			(uint_t)input_chan_bindings->acceptor_address.length;
660 		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val =
661 			(void *) input_chan_bindings->acceptor_address.value;
662 		arg.input_chan_bindings.application_data.GSS_BUFFER_T_len =
663 			(uint_t)input_chan_bindings->application_data.length;
664 		arg.input_chan_bindings.application_data.GSS_BUFFER_T_val =
665 			(void *) input_chan_bindings->application_data.value;
666 	} else {
667 		arg.input_chan_bindings.present = NO;
668 		arg.input_chan_bindings.initiator_addrtype = 0;
669 		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = 0;
670 		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = 0;
671 		arg.input_chan_bindings.acceptor_addrtype = 0;
672 		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = 0;
673 		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = 0;
674 		arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = 0;
675 		arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = 0;
676 	}
677 
678 	arg.input_token.GSS_BUFFER_T_len = (uint_t)
679 		(input_token != GSS_C_NO_BUFFER ? input_token->length : 0);
680 	arg.input_token.GSS_BUFFER_T_val = (char *)
681 		(input_token != GSS_C_NO_BUFFER ? input_token->value : 0);
682 
683 	/* initialize the output parameters to empty values */
684 	if (minor_status != NULL)
685 		*minor_status = DEFAULT_MINOR_STAT;
686 	if (actual_mech_type != NULL)
687 		*actual_mech_type = NULL;
688 	if (output_token != NULL)
689 		output_token->length = 0;
690 	if (ret_flags != NULL)
691 		*ret_flags = 0;
692 	if (time_rec != NULL)
693 		*time_rec = 0;
694 
695 	/* call the remote procedure */
696 	memset(&res, 0, sizeof (res));
697 	if (gss_init_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
698 
699 		/* free the allocated memory for the flattened name */
700 		gss_release_buffer(&minor_status_temp, &external_name);
701 
702 		return (GSS_S_FAILURE);
703 	}
704 
705 	/*
706 	 * We could return from a GSS error here and need to return both the
707 	 * minor_status and output_token, back to the caller if applicable.
708 	 */
709 	if (minor_status != NULL)
710 		*minor_status = res.minor_status;
711 
712 	if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) {
713 		output_token->length =
714 			(size_t)res.output_token.GSS_BUFFER_T_len;
715 		output_token->value =
716 			(void *)res.output_token.GSS_BUFFER_T_val;
717 		res.output_token.GSS_BUFFER_T_val = NULL;
718 		res.output_token.GSS_BUFFER_T_len = 0;
719 	}
720 
721 	/* free the allocated memory for the flattened name */
722 	gss_release_buffer(&minor_status_temp, &external_name);
723 
724 	/* if the call was successful, copy out the results */
725 	if (res.status == (OM_uint32) GSS_S_COMPLETE ||
726 		res.status == (OM_uint32) GSS_S_CONTINUE_NEEDED) {
727 		/*
728 		 * copy the rpc results into the return argument
729 		 * on CONTINUE_NEEDED only ctx handle is ready.
730 		 */
731 		/*LINTED*/
732 		*context_handle = *((OM_uint32 *)
733 			res.context_handle.GSS_CTX_ID_T_val);
734 
735 		*gssd_context_verifier = res.gssd_context_verifier;
736 
737 		/* the rest of the parameters is only ready on COMPLETE */
738 		if (res.status == GSS_S_COMPLETE) {
739 			if (actual_mech_type != NULL) {
740 				*actual_mech_type = (gss_OID)
741 					MALLOC(sizeof (gss_OID_desc));
742 				(*actual_mech_type)->length = (OM_UINT32)
743 					res.actual_mech_type.GSS_OID_len;
744 				(*actual_mech_type)->elements = (void *)
745 					MALLOC((*actual_mech_type)->length);
746 				memcpy((*actual_mech_type)->elements, (void *)
747 					res.actual_mech_type.GSS_OID_val,
748 					(*actual_mech_type)->length);
749 			}
750 
751 
752 			if (ret_flags != NULL)
753 				*ret_flags = res.ret_flags;
754 
755 			if (time_rec != NULL)
756 				*time_rec = res.time_rec;
757 		}
758 	}
759 
760 
761 	/*
762 	 * free the memory allocated for the results and return with the
763 	 * status received in the rpc call.
764 	 */
765 
766 	clnt_freeres(clnt, xdr_gss_init_sec_context_res, (caddr_t)&res);
767 	return (res.status);
768 }
769 OM_uint32
770 kgss_init_sec_context(
771 		OM_uint32 *minor_status,
772 		gss_cred_id_t claimant_cred_handle,
773 		gss_ctx_id_t *context_handle,
774 		gss_name_t target_name,
775 		gss_OID mech_type,
776 		int req_flags,
777 		OM_uint32 time_req,
778 		gss_channel_bindings_t input_chan_bindings,
779 		gss_buffer_t input_token,
780 		gss_OID *actual_mech_type,
781 		gss_buffer_t output_token,
782 		int *ret_flags,
783 		OM_uint32 *time_rec,
784 		uid_t uid)
785 {
786 		OM_uint32	err;
787 		struct kgss_ctx	*kctx;
788 		OM_uint32 gssd_cred_verifier;
789 		gssd_cred_id_t gssd_cl_cred_handle;
790 
791 		/*
792 		 * If this is an initial call, we'll need to create the
793 		 * wrapper struct that contains kernel state information, and
794 		 * a reference to the handle from gssd.
795 		 */
796 		if (*context_handle == GSS_C_NO_CONTEXT) {
797 			kctx = KGSS_ALLOC();
798 			*context_handle = (gss_ctx_id_t)kctx;
799 			kctx->gssd_ctx = (OM_uint32) GSS_C_NO_CONTEXT;
800 		} else
801 			kctx = (struct kgss_ctx *)*context_handle;
802 
803 		if (claimant_cred_handle != GSS_C_NO_CREDENTIAL) {
804 			gssd_cred_verifier =
805 			    KCRED_TO_CREDV(claimant_cred_handle);
806 			gssd_cl_cred_handle =
807 			    KCRED_TO_CRED(claimant_cred_handle);
808 		} else {
809 			gssd_cl_cred_handle = GSSD_NO_CREDENTIAL;
810 		}
811 
812 		err = kgss_init_sec_context_wrapped(minor_status,
813 		    gssd_cl_cred_handle,
814 		    gssd_cred_verifier, &kctx->gssd_ctx,
815 		    &kctx->gssd_ctx_verifier,
816 		    target_name, mech_type, req_flags, time_req,
817 		    input_chan_bindings, input_token, actual_mech_type,
818 		    output_token, ret_flags, time_rec, uid);
819 
820 		if (GSS_ERROR(err)) {
821 			KGSS_FREE(kctx);
822 			*context_handle = GSS_C_NO_CONTEXT;
823 		}
824 		return (err);
825 }
826 OM_uint32
827 kgss_accept_sec_context_wrapped(minor_status,
828 				context_handle,
829 				gssd_context_verifier,
830 				verifier_cred_handle,
831 				gssd_cred_verifier,
832 		input_token,
833 		input_chan_bindings,
834 		src_name,
835 		mech_type,
836 		output_token,
837 		ret_flags,
838 		time_rec,
839 		delegated_cred_handle,
840 		uid)
841 	OM_uint32 *minor_status;
842 	gssd_ctx_id_t *context_handle;
843 	OM_uint32 *gssd_context_verifier;
844 	gssd_cred_id_t verifier_cred_handle;
845 	OM_uint32 gssd_cred_verifier;
846 	gss_buffer_t input_token;
847 	gss_channel_bindings_t input_chan_bindings;
848 	gss_buffer_t src_name;
849 	gss_OID *mech_type;
850 	gss_buffer_t output_token;
851 	int *ret_flags;
852 	OM_uint32 *time_rec;
853 	gss_cred_id_t *delegated_cred_handle;
854 	uid_t uid;
855 {
856 	gss_accept_sec_context_arg arg;
857 	gss_accept_sec_context_res res;
858 	struct kgss_cred *kcred;
859 
860 	/* get the client handle to GSSD */
861 	if ((clnt = getgssd_handle()) == NULL) {
862 		clnt_pcreateerror(server);
863 		return (GSS_S_FAILURE);
864 	}
865 
866 	/* copy the procedure arguments into the rpc arg parameter */
867 	arg.uid = (OM_uint32) uid;
868 
869 	arg.context_handle.GSS_CTX_ID_T_len =
870 		*context_handle == GSSD_NO_CONTEXT ?
871 			0 : (uint_t)sizeof (gssd_ctx_id_t);
872 	arg.context_handle.GSS_CTX_ID_T_val =  (char *)context_handle;
873 	arg.gssd_context_verifier =
874 		*context_handle == (OM_uint32) GSS_C_NO_CONTEXT ?
875 			0 : *gssd_context_verifier;
876 
877 	arg.verifier_cred_handle.GSS_CRED_ID_T_len =
878 			verifier_cred_handle == GSSD_NO_CREDENTIAL ?
879 			0 : (uint_t)sizeof (gssd_cred_id_t);
880 	arg.verifier_cred_handle.GSS_CRED_ID_T_val =
881 						(char *)&verifier_cred_handle;
882 	arg.gssd_cred_verifier = gssd_cred_verifier;
883 
884 	arg.input_token_buffer.GSS_BUFFER_T_len =
885 			(uint_t)(input_token != GSS_C_NO_BUFFER ?
886 					input_token->length : 0);
887 	arg.input_token_buffer.GSS_BUFFER_T_val =
888 			(char *)(input_token != GSS_C_NO_BUFFER ?
889 					input_token->value : 0);
890 
891 	if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) {
892 		arg.input_chan_bindings.present = YES;
893 		arg.input_chan_bindings.initiator_addrtype =
894 			input_chan_bindings->initiator_addrtype;
895 		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len =
896 			(uint_t)input_chan_bindings->initiator_address.length;
897 		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val =
898 			(void *) input_chan_bindings->initiator_address.value;
899 		arg.input_chan_bindings.acceptor_addrtype =
900 			input_chan_bindings->acceptor_addrtype;
901 		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len =
902 			(uint_t)input_chan_bindings->acceptor_address.length;
903 		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val =
904 			(void *) input_chan_bindings->acceptor_address.value;
905 		arg.input_chan_bindings.application_data.GSS_BUFFER_T_len =
906 			(uint_t)input_chan_bindings->application_data.length;
907 		arg.input_chan_bindings.application_data.GSS_BUFFER_T_val =
908 			(void *) input_chan_bindings->application_data.value;
909 	} else {
910 		arg.input_chan_bindings.present = NO;
911 		arg.input_chan_bindings.initiator_addrtype = 0;
912 		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = 0;
913 		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = 0;
914 		arg.input_chan_bindings.acceptor_addrtype = 0;
915 		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = 0;
916 		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = 0;
917 		arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = 0;
918 		arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = 0;
919 	}
920 
921 	/* set the output parameters to empty values.... */
922 	if (minor_status != NULL)
923 		*minor_status = DEFAULT_MINOR_STAT;
924 	if (src_name != NULL) {
925 		src_name->length = 0;
926 		src_name->value = NULL;
927 	}
928 	if (mech_type != NULL)
929 		*mech_type = NULL;
930 	if (output_token != NULL)
931 		output_token->length = 0;
932 	if (ret_flags != NULL)
933 		*ret_flags = 0;
934 	if (time_rec != NULL)
935 		*time_rec = 0;
936 	if (delegated_cred_handle != NULL)
937 		*delegated_cred_handle = NULL;
938 
939 	/* call the remote procedure */
940 	memset(&res, 0, sizeof (res));
941 	if (gss_accept_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
942 		return (GSS_S_FAILURE);
943 	}
944 
945 	/*
946 	 * We could return from a GSS error here and need to return both the
947 	 * minor_status and output_token, back to the caller if applicable.
948 	 */
949 	if (minor_status != NULL)
950 		*minor_status = res.minor_status;
951 
952 	if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) {
953 		output_token->length =
954 			res.output_token.GSS_BUFFER_T_len;
955 		output_token->value =
956 			(void *) res.output_token.GSS_BUFFER_T_val;
957 		res.output_token.GSS_BUFFER_T_val = 0;
958 		res.output_token.GSS_BUFFER_T_len = 0;
959 	}
960 
961 	if (res.status == (OM_uint32) GSS_S_COMPLETE ||
962 		res.status == (OM_uint32) GSS_S_CONTINUE_NEEDED) {
963 		/*
964 		 * when gss returns CONTINUE_NEEDED we can only
965 		 * use the context parameter.
966 		 */
967 		/*LINTED*/
968 		*context_handle = *((gssd_ctx_id_t *)
969 			res.context_handle.GSS_CTX_ID_T_val);
970 		*gssd_context_verifier = res.gssd_context_verifier;
971 
972 		/* the other parameters are ready on for COMPLETE */
973 		if (res.status == GSS_S_COMPLETE)
974 		{
975 
976 			/*
977 			 *  The src_name is in external format.
978 			 */
979 			if (src_name != NULL) {
980 			    src_name->length = res.src_name.GSS_BUFFER_T_len;
981 			    src_name->value = res.src_name.GSS_BUFFER_T_val;
982 			    res.src_name.GSS_BUFFER_T_val = NULL;
983 			    res.src_name.GSS_BUFFER_T_len = 0;
984 			}
985 			/*
986 			 * move mech type returned to mech_type
987 			 * for gss_import_name_for_mech()
988 			 */
989 			if (mech_type != NULL) {
990 				*mech_type =
991 					(gss_OID) MALLOC(sizeof (gss_OID_desc));
992 				(*mech_type)->length =
993 					(OM_UINT32) res.mech_type.GSS_OID_len;
994 				(*mech_type)->elements =
995 					(void *) MALLOC((*mech_type)->length);
996 				memcpy((*mech_type)->elements,
997 					res.mech_type.GSS_OID_val,
998 					(*mech_type)->length);
999 			}
1000 
1001 			if (ret_flags != NULL)
1002 				*ret_flags = res.ret_flags;
1003 
1004 			if (time_rec != NULL)
1005 				*time_rec = res.time_rec;
1006 
1007 			if ((delegated_cred_handle != NULL) &&
1008 				(res.delegated_cred_handle.GSS_CRED_ID_T_len
1009 					!= 0)) {
1010 				kcred = KGSS_CRED_ALLOC();
1011 				/*LINTED*/
1012 				kcred->gssd_cred = *((gssd_cred_id_t *)
1013 				res.delegated_cred_handle.GSS_CRED_ID_T_val);
1014 				kcred->gssd_cred_verifier =
1015 					res.gssd_context_verifier;
1016 				*delegated_cred_handle = (gss_cred_id_t)kcred;
1017 			}
1018 		} /* res.status == GSS_S_COMPLETE */
1019 	} /* res.status == GSS_S_COMPLETE or GSS_CONTINUE_NEEDED */
1020 
1021 
1022 	/*
1023 	 * free the memory allocated for the results and return with the status
1024 	 * received in the rpc call
1025 	 */
1026 
1027 	clnt_freeres(clnt, xdr_gss_accept_sec_context_res, (caddr_t)&res);
1028 	return (res.status);
1029 }
1030 
1031 OM_uint32
1032 kgss_accept_sec_context(
1033 		OM_uint32 *minor_status,
1034 		gss_ctx_id_t *context_handle,
1035 		gss_cred_id_t verifier_cred_handle,
1036 		gss_buffer_t input_token,
1037 		gss_channel_bindings_t input_chan_bindings,
1038 		gss_buffer_t src_name,
1039 		gss_OID *mech_type,
1040 		gss_buffer_t output_token,
1041 		int *ret_flags,
1042 		OM_uint32 *time_rec,
1043 		gss_cred_id_t *delegated_cred_handle,
1044 		uid_t uid)
1045 {
1046 		OM_uint32 err;
1047 		struct kgss_ctx *kctx;
1048 		OM_uint32 gssd_cred_verifier;
1049 		gssd_cred_id_t gssd_ver_cred_handle;
1050 
1051 
1052 		if (*context_handle == GSS_C_NO_CONTEXT) {
1053 			kctx = KGSS_ALLOC();
1054 			*context_handle = (gss_ctx_id_t)kctx;
1055 		kctx->gssd_ctx = GSSD_NO_CONTEXT;
1056 		} else
1057 			kctx = (struct kgss_ctx *)*context_handle;
1058 
1059 	if (verifier_cred_handle != GSS_C_NO_CREDENTIAL) {
1060 			gssd_cred_verifier =
1061 			    KCRED_TO_CREDV(verifier_cred_handle);
1062 			gssd_ver_cred_handle =
1063 			    KCRED_TO_CRED(verifier_cred_handle);
1064 	} else
1065 		gssd_ver_cred_handle = GSSD_NO_CREDENTIAL;
1066 
1067 		err = kgss_accept_sec_context_wrapped(minor_status,
1068 		    &kctx->gssd_ctx,
1069 		    &kctx->gssd_ctx_verifier, gssd_ver_cred_handle,
1070 		    gssd_cred_verifier, input_token, input_chan_bindings,
1071 		    src_name, mech_type, output_token, ret_flags,
1072 		    time_rec, delegated_cred_handle, uid);
1073 
1074 	if (GSS_ERROR(err)) {
1075 		KGSS_FREE(kctx);
1076 		*context_handle = GSS_C_NO_CONTEXT;
1077 
1078 	}
1079 
1080 	return (err);
1081 }
1082 
1083 OM_uint32
1084 kgss_process_context_token(minor_status,
1085 			context_handle,
1086 			token_buffer,
1087 			uid)
1088 	OM_uint32 *minor_status;
1089 	gss_ctx_id_t context_handle;
1090 	gss_buffer_t token_buffer;
1091 	uid_t uid;
1092 {
1093 	OM_uint32 gssd_context_verifier;
1094 
1095 	gss_process_context_token_arg arg;
1096 	gss_process_context_token_res res;
1097 
1098 	gssd_context_verifier = KGSS_CTX_TO_GSSD_CTXV(context_handle);
1099 
1100 	/* get the client handle to GSSD */
1101 
1102 	if ((clnt = getgssd_handle()) == NULL) {
1103 		clnt_pcreateerror(server);
1104 		return (GSS_S_FAILURE);
1105 	}
1106 
1107 	/* copy the procedure arguments into the rpc arg parameter */
1108 	arg.uid = (OM_uint32) uid;
1109 
1110 	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gss_ctx_id_t);
1111 	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
1112 	arg.gssd_context_verifier = gssd_context_verifier;
1113 	arg.token_buffer.GSS_BUFFER_T_len = (uint_t)token_buffer;
1114 	arg.token_buffer.GSS_BUFFER_T_val = (char *)token_buffer->value;
1115 
1116 	/* call the remote procedure */
1117 
1118 	memset(&res, 0, sizeof (res));
1119 	if (gss_process_context_token_1(&arg, &res, clnt) != RPC_SUCCESS) {
1120 
1121 	/*
1122 	 * if the RPC call times out, null out all return arguments,
1123 	 * set minor_status to its maximum value, and return GSS_S_FAILURE
1124 	 */
1125 
1126 		if (minor_status != NULL)
1127 			*minor_status = DEFAULT_MINOR_STAT;
1128 
1129 		return (GSS_S_FAILURE);
1130 	}
1131 
1132 	/* copy the rpc results into the return arguments */
1133 
1134 	if (minor_status != NULL)
1135 		*minor_status = res.minor_status;
1136 
1137 	/* return with status returned in rpc call */
1138 
1139 	return (res.status);
1140 }
1141 
1142 OM_uint32
1143 kgss_delete_sec_context_wrapped(minor_status,
1144 			context_handle,
1145 			gssd_context_verifier,
1146 			output_token)
1147 	OM_uint32 *minor_status;
1148 	gssd_ctx_id_t *context_handle;
1149 	OM_uint32 gssd_context_verifier;
1150 	gss_buffer_t output_token;
1151 {
1152 	gss_delete_sec_context_arg arg;
1153 	gss_delete_sec_context_res res;
1154 
1155 
1156 	/* get the client handle to GSSD */
1157 	if ((clnt = getgssd_handle()) == NULL) {
1158 		clnt_pcreateerror(server);
1159 		return (GSS_S_FAILURE);
1160 	}
1161 
1162 	/* copy the procedure arguments into the rpc arg parameter */
1163 
1164 	arg.context_handle.GSS_CTX_ID_T_len =
1165 		*context_handle == (OM_uint32) GSS_C_NO_CONTEXT ? 0 :
1166 		(uint_t)sizeof (OM_uint32);
1167 	arg.context_handle.GSS_CTX_ID_T_val =  (char *)context_handle;
1168 
1169 	arg.gssd_context_verifier = gssd_context_verifier;
1170 
1171 	/* call the remote procedure */
1172 
1173 	memset(&res, 0, sizeof (res));
1174 	if (gss_delete_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
1175 
1176 		/*
1177 		 * if the RPC call times out, null out all return arguments,
1178 		 * set minor_status to its max value, and return GSS_S_FAILURE
1179 		 */
1180 
1181 		if (minor_status != NULL)
1182 			*minor_status = DEFAULT_MINOR_STAT;
1183 		if (context_handle != NULL)
1184 			*context_handle = NULL;
1185 		if (output_token != NULL)
1186 			output_token->length = 0;
1187 
1188 		return (GSS_S_FAILURE);
1189 	}
1190 
1191 	/* copy the rpc results into the return arguments */
1192 
1193 	if (minor_status != NULL)
1194 		*minor_status = res.minor_status;
1195 
1196 	if (res.context_handle.GSS_CTX_ID_T_len == 0)
1197 		*context_handle = NULL;
1198 	else
1199 		/*LINTED*/
1200 		*context_handle = *((gssd_ctx_id_t *)
1201 			res.context_handle.GSS_CTX_ID_T_val);
1202 
1203 	if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) {
1204 		output_token->length = res.output_token.GSS_BUFFER_T_len;
1205 		output_token->value = res.output_token.GSS_BUFFER_T_val;
1206 		res.output_token.GSS_BUFFER_T_len = 0;
1207 		res.output_token.GSS_BUFFER_T_val = NULL;
1208 	}
1209 
1210 	/*
1211 	 * free the memory allocated for the results and return with the status
1212 	 * received in the rpc call
1213 	 */
1214 
1215 	clnt_freeres(clnt, xdr_gss_delete_sec_context_res, (caddr_t)&res);
1216 	return (res.status);
1217 }
1218 
1219 /*ARGSUSED*/
1220 OM_uint32
1221 kgss_delete_sec_context(
1222 		OM_uint32 *minor_status,
1223 		gss_ctx_id_t *context_handle,
1224 		gss_buffer_t output_token)
1225 {
1226 		OM_uint32 err;
1227 		struct kgss_ctx *kctx;
1228 
1229 		if (*context_handle == GSS_C_NO_CONTEXT) {
1230 			return (GSS_S_NO_CONTEXT);
1231 		} else
1232 			kctx = KCTX_TO_KGSS_CTX(*context_handle);
1233 
1234 		err = kgss_delete_sec_context_wrapped(minor_status,
1235 		    &kctx->gssd_ctx, kctx->gssd_ctx_verifier,
1236 		    output_token);
1237 
1238 		if (kctx->gssd_ctx != GSSD_NO_CONTEXT)
1239 			err = GSS_S_FAILURE;
1240 		else
1241 			err = GSS_S_COMPLETE;
1242 
1243 		KGSS_FREE(kctx);
1244 		*context_handle = GSS_C_NO_CONTEXT;
1245 		return (err);
1246 }
1247 
1248 /*ARGSUSED*/
1249 OM_uint32
1250 kgss_context_time(minor_status,
1251 		context_handle,
1252 		time_rec,
1253 		uid)
1254 	OM_uint32 *minor_status;
1255 	gss_ctx_id_t context_handle;
1256 	OM_uint32 *time_rec;
1257 	uid_t uid;
1258 {
1259 	return (GSS_S_FAILURE);
1260 }
1261 
1262 OM_uint32
1263 kgss_sign_wrapped(minor_status,
1264 		context_handle,
1265 		qop_req,
1266 		message_buffer,
1267 		msg_token,
1268 		gssd_context_verifier)
1269 	OM_uint32 *minor_status;
1270 	gssd_ctx_id_t context_handle;
1271 	OM_uint32 gssd_context_verifier;
1272 	int qop_req;
1273 	gss_buffer_t message_buffer;
1274 	gss_buffer_t msg_token;
1275 {
1276 
1277 	gss_sign_arg arg;
1278 	gss_sign_res res;
1279 
1280 	/* get the client handle to GSSD */
1281 
1282 	if ((clnt = getgssd_handle()) == NULL) {
1283 		clnt_pcreateerror(server);
1284 		return (GSS_S_FAILURE);
1285 	}
1286 
1287 	/* copy the procedure arguments into the rpc arg parameter */
1288 
1289 
1290 	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
1291 	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
1292 	arg.gssd_context_verifier = gssd_context_verifier;
1293 
1294 	arg.qop_req = qop_req;
1295 	arg.message_buffer.GSS_BUFFER_T_len = (uint_t)message_buffer->length;
1296 	arg.message_buffer.GSS_BUFFER_T_val = (char *)message_buffer->value;
1297 
1298 	/* call the remote procedure */
1299 
1300 	memset(&res, 0, sizeof (res));
1301 	if (gss_sign_1(&arg, &res, clnt) != RPC_SUCCESS) {
1302 
1303 	/*
1304 	 * if the RPC call times out, null out all return arguments,
1305 	 * set minor_status to its maximum value, and return GSS_S_FAILURE
1306 	 */
1307 
1308 		if (minor_status != NULL)
1309 			*minor_status = DEFAULT_MINOR_STAT;
1310 		if (msg_token != NULL)
1311 			msg_token->length = 0;
1312 
1313 		return (GSS_S_FAILURE);
1314 	}
1315 
1316 	/* copy the rpc results into the return arguments */
1317 
1318 	if (minor_status != NULL)
1319 		*minor_status = res.minor_status;
1320 
1321 	if (msg_token != NULL) {
1322 		msg_token->length = res.msg_token.GSS_BUFFER_T_len;
1323 		msg_token->value = (void *) MALLOC(msg_token->length);
1324 		memcpy(msg_token->value, res.msg_token.GSS_BUFFER_T_val,
1325 			msg_token->length);
1326 	}
1327 
1328 	/*
1329 	 * free the memory allocated for the results and return with the status
1330 	 * received in the rpc call
1331 	 */
1332 
1333 	clnt_freeres(clnt, xdr_gss_sign_res, (caddr_t)&res);
1334 	return (res.status);
1335 }
1336 
1337 OM_uint32
1338 kgss_sign(
1339 		OM_uint32 *minor_status,
1340 		gss_ctx_id_t context_handle,
1341 		int qop_req,
1342 		gss_buffer_t message_buffer,
1343 		gss_buffer_t msg_token)
1344 {
1345 		if (context_handle == GSS_C_NO_CONTEXT)
1346 			return (GSS_S_FAILURE);
1347 
1348 		return (KGSS_SIGN(minor_status,
1349 		    context_handle, qop_req, message_buffer,
1350 		    msg_token));
1351 }
1352 
1353 OM_uint32
1354 kgss_verify_wrapped(
1355 		minor_status,
1356 		context_handle,
1357 		message_buffer,
1358 		token_buffer,
1359 		qop_state,
1360 		gssd_context_verifier)
1361 	OM_uint32 *minor_status;
1362 	gssd_ctx_id_t context_handle;
1363 	OM_uint32 gssd_context_verifier;
1364 	gss_buffer_t message_buffer;
1365 	gss_buffer_t token_buffer;
1366 	int *qop_state;
1367 {
1368 	gss_verify_arg arg;
1369 	gss_verify_res res;
1370 
1371 /* get the client handle to GSSD */
1372 
1373 	if ((clnt = getgssd_handle()) == NULL) {
1374 		clnt_pcreateerror(server);
1375 		return (GSS_S_FAILURE);
1376 	}
1377 
1378 	/* copy the procedure arguments into the rpc arg parameter */
1379 
1380 	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
1381 	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
1382 
1383 	arg.gssd_context_verifier = gssd_context_verifier;
1384 
1385 	arg.message_buffer.GSS_BUFFER_T_len = (uint_t)message_buffer->length;
1386 	arg.message_buffer.GSS_BUFFER_T_val = (char *)message_buffer->value;
1387 
1388 	arg.token_buffer.GSS_BUFFER_T_len = (uint_t)token_buffer->length;
1389 	arg.token_buffer.GSS_BUFFER_T_val = (char *)token_buffer->value;
1390 
1391 	/* call the remote procedure */
1392 
1393 	memset(&res, 0, sizeof (res));
1394 	if (gss_verify_1(&arg, &res, clnt) != RPC_SUCCESS) {
1395 
1396 	/*
1397 	 * if the RPC call times out, null out all return arguments,
1398 	 * set minor_status to its maximum value, and return GSS_S_FAILURE
1399 	 */
1400 
1401 		if (minor_status != NULL)
1402 			*minor_status = DEFAULT_MINOR_STAT;
1403 		if (qop_state != NULL)
1404 			*qop_state = 0;
1405 
1406 		return (GSS_S_FAILURE);
1407 	}
1408 
1409 	/* copy the rpc results into the return arguments */
1410 
1411 	if (minor_status != NULL)
1412 		*minor_status = res.minor_status;
1413 
1414 	if (qop_state != NULL)
1415 		*qop_state = res.qop_state;
1416 
1417 	/* return with status returned in rpc call */
1418 
1419 	return (res.status);
1420 }
1421 
1422 OM_uint32
1423 kgss_verify(OM_uint32 *minor_status,
1424 	gss_ctx_id_t context_handle,
1425 	gss_buffer_t message_buffer,
1426 	gss_buffer_t token_buffer,
1427 	int *qop_state)
1428 {
1429 		if (context_handle == GSS_C_NO_CONTEXT)
1430 			return (GSS_S_FAILURE);
1431 
1432 		return (KGSS_VERIFY(minor_status, context_handle,
1433 		    message_buffer, token_buffer, qop_state));
1434 }
1435 
1436 
1437 /* EXPORT DELETE START */
1438 
1439 OM_uint32
1440 kgss_seal_wrapped(
1441 	minor_status,
1442 	context_handle,
1443 	conf_req_flag,
1444 	qop_req,
1445 	input_message_buffer,
1446 	conf_state,
1447 	output_message_buffer,
1448 	gssd_context_verifier)
1449 
1450 	OM_uint32 *minor_status;
1451 	gssd_ctx_id_t context_handle;
1452 	OM_uint32 gssd_context_verifier;
1453 	int conf_req_flag;
1454 	int qop_req;
1455 	gss_buffer_t input_message_buffer;
1456 	int *conf_state;
1457 	gss_buffer_t output_message_buffer;
1458 {
1459 	gss_seal_arg arg;
1460 	gss_seal_res res;
1461 
1462 	/* get the client handle to GSSD */
1463 
1464 	if ((clnt = getgssd_handle()) == NULL) {
1465 		clnt_pcreateerror(server);
1466 		return (GSS_S_FAILURE);
1467 	}
1468 
1469 	/* copy the procedure arguments into the rpc arg parameter */
1470 
1471 
1472 	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
1473 	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
1474 	arg.gssd_context_verifier = gssd_context_verifier;
1475 
1476 	arg.conf_req_flag = conf_req_flag;
1477 
1478 	arg.qop_req = qop_req;
1479 
1480 	arg.input_message_buffer.GSS_BUFFER_T_len =
1481 				(uint_t)input_message_buffer->length;
1482 
1483 	arg.input_message_buffer.GSS_BUFFER_T_val =
1484 				(char *)input_message_buffer->value;
1485 
1486 	/* call the remote procedure */
1487 
1488 	memset(&res, 0, sizeof (res));
1489 	if (gss_seal_1(&arg, &res, clnt) != RPC_SUCCESS) {
1490 
1491 	/*
1492 	 * if the RPC call times out, null out all return arguments,
1493 	 * set minor_status to its maximum value, and return GSS_S_FAILURE
1494 	 */
1495 
1496 		if (minor_status != NULL)
1497 			*minor_status = DEFAULT_MINOR_STAT;
1498 		if (conf_state != NULL)
1499 			*conf_state = 0;
1500 		if (output_message_buffer != NULL)
1501 			output_message_buffer->length = 0;
1502 
1503 		return (GSS_S_FAILURE);
1504 	}
1505 
1506 	/* copy the rpc results into the return arguments */
1507 
1508 	if (minor_status != NULL)
1509 		*minor_status = res.minor_status;
1510 
1511 	if (conf_state != NULL)
1512 		*conf_state = res.conf_state;
1513 
1514 	if (output_message_buffer != NULL) {
1515 		output_message_buffer->length =
1516 				res.output_message_buffer.GSS_BUFFER_T_len;
1517 
1518 		output_message_buffer->value =
1519 				(void *) MALLOC(output_message_buffer->length);
1520 		memcpy(output_message_buffer->value,
1521 			res.output_message_buffer.GSS_BUFFER_T_val,
1522 			output_message_buffer->length);
1523 	}
1524 
1525 	/*
1526 	 * free the memory allocated for the results and return with the status
1527 	 * received in the rpc call
1528 	 */
1529 
1530 	clnt_freeres(clnt, xdr_gss_seal_res, (caddr_t)&res);
1531 	return (res.status);
1532 }
1533 
1534 OM_uint32
1535 kgss_seal(OM_uint32 *minor_status,
1536 		gss_ctx_id_t context_handle,
1537 		int conf_req_flag,
1538 		int qop_req,
1539 		gss_buffer_t input_message_buffer,
1540 		int *conf_state,
1541 		gss_buffer_t output_message_buffer)
1542 
1543 {
1544 		if (context_handle == GSS_C_NO_CONTEXT)
1545 			return (GSS_S_FAILURE);
1546 
1547 		return (KGSS_SEAL(minor_status, context_handle,
1548 			conf_req_flag, qop_req,
1549 			input_message_buffer,
1550 			conf_state, output_message_buffer));
1551 }
1552 
1553 OM_uint32
1554 kgss_unseal_wrapped(minor_status,
1555 		context_handle,
1556 		input_message_buffer,
1557 		output_message_buffer,
1558 		conf_state,
1559 		qop_state,
1560 		gssd_context_verifier)
1561 	OM_uint32 *minor_status;
1562 	gssd_ctx_id_t context_handle;
1563 	OM_uint32 gssd_context_verifier;
1564 	gss_buffer_t input_message_buffer;
1565 	gss_buffer_t output_message_buffer;
1566 	int *conf_state;
1567 	int *qop_state;
1568 {
1569 	gss_unseal_arg arg;
1570 	gss_unseal_res res;
1571 
1572 	/* get the client handle to GSSD */
1573 
1574 	if ((clnt = getgssd_handle()) == NULL) {
1575 		clnt_pcreateerror(server);
1576 		return (GSS_S_FAILURE);
1577 	}
1578 
1579 	/* copy the procedure arguments into the rpc arg parameter */
1580 
1581 
1582 	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
1583 	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
1584 	arg.gssd_context_verifier = gssd_context_verifier;
1585 
1586 	arg.input_message_buffer.GSS_BUFFER_T_len =
1587 				(uint_t)input_message_buffer->length;
1588 
1589 	arg.input_message_buffer.GSS_BUFFER_T_val =
1590 				(char *)input_message_buffer->value;
1591 
1592 /* call the remote procedure */
1593 
1594 	memset(&res, 0, sizeof (res));
1595 	if (gss_unseal_1(&arg, &res, clnt) != RPC_SUCCESS) {
1596 
1597 	/*
1598 	 * if the RPC call times out, null out all return arguments,
1599 	 * set minor_status to its maximum value, and return GSS_S_FAILURE
1600 	 */
1601 
1602 		if (minor_status != NULL)
1603 			*minor_status = DEFAULT_MINOR_STAT;
1604 		if (output_message_buffer != NULL)
1605 			output_message_buffer->length = 0;
1606 		if (conf_state != NULL)
1607 			*conf_state = 0;
1608 		if (qop_state != NULL)
1609 			*qop_state = 0;
1610 
1611 		return (GSS_S_FAILURE);
1612 	}
1613 
1614 	/* copy the rpc results into the return arguments */
1615 
1616 	if (minor_status != NULL)
1617 		*minor_status = res.minor_status;
1618 
1619 	if (output_message_buffer != NULL) {
1620 		output_message_buffer->length =
1621 				res.output_message_buffer.GSS_BUFFER_T_len;
1622 
1623 		output_message_buffer->value =
1624 			(void *) MALLOC(output_message_buffer->length);
1625 		memcpy(output_message_buffer->value,
1626 			res.output_message_buffer.GSS_BUFFER_T_val,
1627 			output_message_buffer->length);
1628 	}
1629 
1630 	if (conf_state != NULL)
1631 		*conf_state = res.conf_state;
1632 
1633 	if (qop_state != NULL)
1634 		*qop_state = res.qop_state;
1635 
1636 	/*
1637 	 * free the memory allocated for the results and return with the status
1638 	 * received in the rpc call
1639 	 */
1640 
1641 	clnt_freeres(clnt, xdr_gss_unseal_res, (caddr_t)&res);
1642 	return (res.status);
1643 }
1644 
1645 OM_uint32
1646 kgss_unseal(OM_uint32 *minor_status,
1647 	gss_ctx_id_t context_handle,
1648 	gss_buffer_t input_message_buffer,
1649 	gss_buffer_t output_message_buffer,
1650 	int *conf_state,
1651 	int *qop_state)
1652 {
1653 		if (context_handle == GSS_C_NO_CONTEXT)
1654 			return (GSS_S_FAILURE);
1655 
1656 		return (KGSS_UNSEAL(minor_status, context_handle,
1657 		    input_message_buffer, output_message_buffer,
1658 		    conf_state, qop_state));
1659 }
1660 
1661 /* EXPORT DELETE END */
1662 
1663 OM_uint32
1664 kgss_display_status(minor_status,
1665 		status_value,
1666 		status_type,
1667 		mech_type,
1668 		message_context,
1669 		status_string,
1670 		uid)
1671 	OM_uint32 *minor_status;
1672 	OM_uint32 status_value;
1673 	int status_type;
1674 	gss_OID mech_type;
1675 	int *message_context;
1676 	gss_buffer_t status_string;
1677 	uid_t uid;
1678 {
1679 	gss_display_status_arg arg;
1680 	gss_display_status_res res;
1681 
1682 	/* get the client handle to GSSD */
1683 
1684 	if ((clnt = getgssd_handle()) == NULL) {
1685 		clnt_pcreateerror(server);
1686 		return (GSS_S_FAILURE);
1687 	}
1688 
1689 	/* copy the procedure arguments into the rpc arg parameter */
1690 
1691 	arg.uid = (OM_uint32) uid;
1692 
1693 	arg.status_value = status_value;
1694 	arg.status_type = status_type;
1695 
1696 	arg.mech_type.GSS_OID_len = (uint_t)(mech_type != GSS_C_NULL_OID ?
1697 					mech_type->length : 0);
1698 	arg.mech_type.GSS_OID_val = (char *)(mech_type != GSS_C_NULL_OID ?
1699 					mech_type->elements : 0);
1700 
1701 	arg.message_context = *message_context;
1702 
1703 	/* call the remote procedure */
1704 
1705 	if (message_context != NULL)
1706 		*message_context = 0;
1707 	if (status_string != NULL) {
1708 		status_string->length = 0;
1709 		status_string->value = NULL;
1710 	}
1711 
1712 	memset(&res, 0, sizeof (res));
1713 	if (gss_display_status_1(&arg, &res, clnt) != RPC_SUCCESS) {
1714 
1715 	/*
1716 	 * if the RPC call times out, null out all return arguments,
1717 	 * set minor_status to its maximum value, and return GSS_S_FAILURE
1718 	 */
1719 
1720 		if (minor_status != NULL)
1721 			*minor_status = DEFAULT_MINOR_STAT;
1722 
1723 		return (GSS_S_FAILURE);
1724 	}
1725 
1726 	if (minor_status != NULL)
1727 		*minor_status = res.minor_status;
1728 
1729 	/* now process the results and pass them back to the caller */
1730 
1731 	if (res.status == GSS_S_COMPLETE) {
1732 		if (message_context != NULL)
1733 			*message_context = res.message_context;
1734 		if (status_string != NULL) {
1735 			status_string->length =
1736 				(size_t)res.status_string.GSS_BUFFER_T_len;
1737 			status_string->value =
1738 				(void *)MALLOC(status_string->length);
1739 			memcpy(status_string->value,
1740 				res.status_string.GSS_BUFFER_T_val,
1741 				status_string->length);
1742 		}
1743 	}
1744 
1745 	clnt_freeres(clnt, xdr_gss_display_status_res, (caddr_t)&res);
1746 	return (res.status);
1747 }
1748 
1749 /*ARGSUSED*/
1750 OM_uint32
1751 kgss_indicate_mechs(minor_status,
1752 		mech_set,
1753 		uid)
1754 	OM_uint32 *minor_status;
1755 	gss_OID_set *mech_set;
1756 	uid_t uid;
1757 {
1758 	void *arg;
1759 	gss_indicate_mechs_res res;
1760 	int i;
1761 
1762 	/* get the client handle to GSSD */
1763 
1764 	if ((clnt = getgssd_handle()) == NULL) {
1765 		clnt_pcreateerror(server);
1766 		return (GSS_S_FAILURE);
1767 	}
1768 
1769 	memset(&res, 0, sizeof (res));
1770 	if (gss_indicate_mechs_1(&arg, &res, clnt) != RPC_SUCCESS) {
1771 
1772 	/*
1773 	 * if the RPC call times out, null out all return arguments,
1774 	 * set minor_status to its maximum value, and return GSS_S_FAILURE
1775 	 */
1776 
1777 		if (minor_status != NULL)
1778 			*minor_status = DEFAULT_MINOR_STAT;
1779 		if (mech_set != NULL)
1780 			*mech_set = NULL;
1781 
1782 		return (GSS_S_FAILURE);
1783 	}
1784 
1785 	/* copy the rpc results into the return arguments */
1786 
1787 	if (minor_status != NULL)
1788 		*minor_status = res.minor_status;
1789 
1790 	if (mech_set != NULL) {
1791 		*mech_set = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
1792 		(*mech_set)->count = res.mech_set.GSS_OID_SET_len;
1793 		(*mech_set)->elements = (void *)
1794 			MALLOC ((*mech_set)->count * sizeof (gss_OID_desc));
1795 		for (i = 0; i < (*mech_set)->count; i++) {
1796 			(*mech_set)->elements[i].length =
1797 				res.mech_set.GSS_OID_SET_val[i].GSS_OID_len;
1798 			(*mech_set)->elements[i].elements = (void *)
1799 				MALLOC ((*mech_set)->elements[i].length);
1800 			memcpy ((*mech_set)->elements[i].elements,
1801 				res.mech_set.GSS_OID_SET_val[i].GSS_OID_val,
1802 				(*mech_set)->elements[i].length);
1803 		}
1804 	}
1805 
1806 	/*
1807 	 * free the memory allocated for the results and return with the status
1808 	 * received in the rpc call
1809 	 */
1810 
1811 	clnt_freeres(clnt, xdr_gss_indicate_mechs_res, (caddr_t)&res);
1812 	return (res.status);
1813 }
1814 
1815 
1816 OM_uint32
1817 kgss_inquire_cred_wrapped(minor_status,
1818 			cred_handle,
1819 			gssd_cred_verifier,
1820 			name,
1821 			lifetime,
1822 			cred_usage,
1823 			mechanisms,
1824 			uid)
1825 	OM_uint32 *minor_status;
1826 	gssd_cred_id_t cred_handle;
1827 	OM_uint32 gssd_cred_verifier;
1828 	gss_name_t *name;
1829 	OM_uint32 *lifetime;
1830 	int *cred_usage;
1831 	gss_OID_set *mechanisms;
1832 	uid_t uid;
1833 {
1834 	OM_uint32 minor_status_temp;
1835 	gss_buffer_desc external_name;
1836 	gss_OID name_type;
1837 	int i;
1838 
1839 	gss_inquire_cred_arg arg;
1840 	gss_inquire_cred_res res;
1841 
1842 	/* get the client handle to GSSD */
1843 
1844 	if ((clnt = getgssd_handle()) == NULL) {
1845 		clnt_pcreateerror(server);
1846 		return (GSS_S_FAILURE);
1847 	}
1848 
1849 
1850 	/* copy the procedure arguments into the rpc arg parameter */
1851 
1852 	arg.uid = (OM_uint32) uid;
1853 
1854 	arg.cred_handle.GSS_CRED_ID_T_len =
1855 			cred_handle == GSSD_NO_CREDENTIAL ?
1856 			0 : (uint_t)sizeof (gssd_cred_id_t);
1857 	arg.cred_handle.GSS_CRED_ID_T_val = (char *)&cred_handle;
1858 	arg.gssd_cred_verifier = gssd_cred_verifier;
1859 
1860 	/* call the remote procedure */
1861 
1862 	memset(&res, 0, sizeof (res));
1863 	if (gss_inquire_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
1864 
1865 	/*
1866 	 * if the RPC call times out, null out all return arguments,
1867 	 * set minor_status to its maximum value, and return GSS_S_FAILURE
1868 	 */
1869 
1870 		if (minor_status != NULL)
1871 			*minor_status = DEFAULT_MINOR_STAT;
1872 		if (name != NULL)
1873 			*name = NULL;
1874 		if (lifetime != NULL)
1875 			*lifetime = 0;
1876 		if (cred_usage != NULL)
1877 			*cred_usage = 0;
1878 		if (mechanisms != NULL)
1879 			*mechanisms = NULL;
1880 
1881 		return (GSS_S_FAILURE);
1882 	}
1883 
1884 	/* copy the rpc results into the return arguments */
1885 
1886 	if (minor_status != NULL)
1887 		*minor_status = res.minor_status;
1888 
1889 	/* convert name from external to internal format */
1890 
1891 	if (name != NULL) {
1892 		external_name.length = res.name.GSS_BUFFER_T_len;
1893 		external_name.value = res.name.GSS_BUFFER_T_val;
1894 
1895 		/*
1896 		 * we have to allocate a name_type descriptor and
1897 		 * elements storage, since gss_import_name() only
1898 		 * stores a pointer to the name_type info in the
1899 		 * union_name struct
1900 		 */
1901 
1902 		name_type = (gss_OID) MALLOC(sizeof (gss_OID_desc));
1903 
1904 		name_type->length = res.name_type.GSS_OID_len;
1905 		name_type->elements = (void *) MALLOC(name_type->length);
1906 		memcpy(name_type->elements, res.name_type.GSS_OID_val,
1907 			name_type->length);
1908 
1909 		if (gss_import_name(&minor_status_temp, &external_name,
1910 			name_type, name) != GSS_S_COMPLETE) {
1911 
1912 			*minor_status = (OM_uint32) minor_status_temp;
1913 			gss_release_buffer(&minor_status_temp, &external_name);
1914 
1915 			clnt_freeres(clnt, xdr_gss_inquire_cred_res,
1916 							(caddr_t)&res);
1917 			return ((OM_uint32) GSS_S_FAILURE);
1918 		}
1919 	}
1920 
1921 	if (lifetime != NULL)
1922 		*lifetime = res.lifetime;
1923 
1924 	if (cred_usage != NULL)
1925 		*cred_usage = res.cred_usage;
1926 
1927 	if (mechanisms != NULL) {
1928 		*mechanisms =
1929 			(gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
1930 		if (res.mechanisms.GSS_OID_SET_len != 0) {
1931 			(*mechanisms)->count =
1932 					(int)res.mechanisms.GSS_OID_SET_len;
1933 			(*mechanisms)->elements = (gss_OID)
1934 				MALLOC(sizeof (gss_OID) * (*mechanisms)->count);
1935 
1936 			for (i = 0; i < (*mechanisms)->count; i++) {
1937 				(*mechanisms)->elements[i].length = (OM_uint32)
1938 				res.mechanisms.GSS_OID_SET_val[i].GSS_OID_len;
1939 				(*mechanisms)->elements[i].elements = (void *)
1940 				MALLOC((*mechanisms)->elements[i].length);
1941 				memcpy((*mechanisms)->elements[i].elements,
1942 				res.mechanisms.GSS_OID_SET_val[i].GSS_OID_val,
1943 				(*mechanisms)->elements[i].length);
1944 			}
1945 		} else
1946 			(*mechanisms)->count = 0;
1947 	}
1948 
1949 	/*
1950 	 * free the memory allocated for the results and return with the status
1951 	 * received in the rpc call
1952 	 */
1953 
1954 	clnt_freeres(clnt, xdr_gss_inquire_cred_res, (caddr_t)&res);
1955 	return (res.status);
1956 }
1957 
1958 
1959 OM_uint32
1960 kgss_inquire_cred(minor_status,
1961 			cred_handle,
1962 			name,
1963 			lifetime,
1964 			cred_usage,
1965 			mechanisms,
1966 			uid)
1967 	OM_uint32 *minor_status;
1968 	gss_cred_id_t cred_handle;
1969 	gss_name_t *name;
1970 	OM_uint32 *lifetime;
1971 	int *cred_usage;
1972 	gss_OID_set * mechanisms;
1973 	uid_t uid;
1974 {
1975 
1976 	OM_uint32 gssd_cred_verifier;
1977 	gssd_cred_id_t gssd_cred_handle;
1978 
1979 		gssd_cred_verifier = KCRED_TO_CREDV(cred_handle);
1980 		gssd_cred_handle = KCRED_TO_CRED(cred_handle);
1981 
1982 		return (kgss_inquire_cred_wrapped(minor_status,
1983 				gssd_cred_handle, gssd_cred_verifier,
1984 				name, lifetime, cred_usage, mechanisms, uid));
1985 }
1986 
1987 
1988 OM_uint32
1989 kgss_inquire_cred_by_mech_wrapped(minor_status,
1990 			cred_handle,
1991 			gssd_cred_verifier,
1992 			mech_type,
1993 			uid)
1994 	OM_uint32 *minor_status;
1995 	gssd_cred_id_t cred_handle;
1996 	OM_uint32 gssd_cred_verifier;
1997 	gss_OID mech_type;
1998 	uid_t uid;
1999 {
2000 	OM_uint32 minor_status_temp;
2001 
2002 	gss_inquire_cred_by_mech_arg arg;
2003 	gss_inquire_cred_by_mech_res res;
2004 
2005 	/* get the client handle to GSSD */
2006 
2007 	if ((clnt = getgssd_handle()) == NULL) {
2008 		clnt_pcreateerror(server);
2009 		return (GSS_S_FAILURE);
2010 	}
2011 
2012 
2013 	/* copy the procedure arguments into the rpc arg parameter */
2014 
2015 	arg.uid = (OM_uint32) uid;
2016 
2017 	arg.cred_handle.GSS_CRED_ID_T_len =
2018 			cred_handle == GSSD_NO_CREDENTIAL ?
2019 			0 : (uint_t)sizeof (gssd_cred_id_t);
2020 	arg.cred_handle.GSS_CRED_ID_T_val = (char *)&cred_handle;
2021 	arg.gssd_cred_verifier = gssd_cred_verifier;
2022 
2023 	arg.mech_type.GSS_OID_len =
2024 		(uint_t)(mech_type != GSS_C_NULL_OID ?
2025 		mech_type->length : 0);
2026 	arg.mech_type.GSS_OID_val =
2027 		(char *)(mech_type != GSS_C_NULL_OID ?
2028 		mech_type->elements : 0);
2029 	/* call the remote procedure */
2030 
2031 	memset(&res, 0, sizeof (res));
2032 	if (gss_inquire_cred_by_mech_1(&arg, &res, clnt) != RPC_SUCCESS) {
2033 
2034 	/*
2035 	 * if the RPC call times out, null out all return arguments,
2036 	 * set minor_status to its maximum value, and return GSS_S_FAILURE
2037 	 */
2038 
2039 		if (minor_status != NULL)
2040 			*minor_status = DEFAULT_MINOR_STAT;
2041 		return (GSS_S_FAILURE);
2042 	}
2043 
2044 	/* copy the rpc results into the return arguments */
2045 
2046 	if (minor_status != NULL)
2047 		*minor_status = res.minor_status;
2048 
2049 	/* convert name from external to internal format */
2050 
2051 	/*
2052 	 * free the memory allocated for the results and return with the status
2053 	 * received in the rpc call
2054 	 */
2055 
2056 	clnt_freeres(clnt, xdr_gss_inquire_cred_by_mech_res, (caddr_t)&res);
2057 	return (res.status);
2058 }
2059 
2060 
2061 OM_uint32
2062 kgss_inquire_cred_by_mech(minor_status,
2063 			cred_handle,
2064 			mech_type,
2065 			uid)
2066 	OM_uint32 *minor_status;
2067 	gss_cred_id_t cred_handle;
2068 	gss_OID mech_type;
2069 	uid_t uid;
2070 {
2071 
2072 	OM_uint32 gssd_cred_verifier;
2073 	gssd_cred_id_t gssd_cred_handle;
2074 
2075 	gssd_cred_verifier = KCRED_TO_CREDV(cred_handle);
2076 	gssd_cred_handle = KCRED_TO_CRED(cred_handle);
2077 
2078 	return (kgss_inquire_cred_by_mech_wrapped(minor_status,
2079 			gssd_cred_handle, gssd_cred_verifier,
2080 			mech_type, uid));
2081 }
2082 
2083 OM_uint32
2084 kgsscred_expname_to_unix_cred(expName, uidOut, gidOut, gids, gidsLen, uid)
2085 	const gss_buffer_t expName;
2086 	uid_t *uidOut;
2087 	gid_t *gidOut;
2088 	gid_t *gids[];
2089 	int *gidsLen;
2090 	uid_t uid;
2091 {
2092 	gsscred_expname_to_unix_cred_arg args;
2093 	gsscred_expname_to_unix_cred_res res;
2094 
2095 	/* check input/output parameters */
2096 	if (expName == NULL || expName->value == NULL)
2097 		return (GSS_S_CALL_INACCESSIBLE_READ);
2098 
2099 	if (uidOut == NULL)
2100 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
2101 
2102 	/* NULL out output parameters */
2103 	*uidOut = 0;
2104 	if (gidsLen)
2105 		*gidsLen = 0;
2106 
2107 	if (gids)
2108 		*gids = NULL;
2109 
2110 	/* get the client handle to gssd */
2111 	if ((clnt = getgssd_handle()) == NULL)
2112 	{
2113 		clnt_pcreateerror(server);
2114 		return (GSS_S_FAILURE);
2115 	}
2116 
2117 	/* copy the procedure arguments */
2118 	args.uid = uid;
2119 	args.expname.GSS_BUFFER_T_val = expName->value;
2120 	args.expname.GSS_BUFFER_T_len = expName->length;
2121 
2122 	/* null out the return buffer and call the remote proc */
2123 	memset(&res, 0, sizeof (res));
2124 
2125 	if (gsscred_expname_to_unix_cred_1(&args, &res, clnt) != RPC_SUCCESS)
2126 	{
2127 		return (GSS_S_FAILURE);
2128 	}
2129 
2130 	/* copy the results into the result parameters */
2131 	if (res.major == GSS_S_COMPLETE)
2132 	{
2133 		*uidOut = res.uid;
2134 		if (gidOut)
2135 			*gidOut = res.gid;
2136 		if (gids && gidsLen)
2137 		{
2138 			*gids = res.gids.GSSCRED_GIDS_val;
2139 			*gidsLen = res.gids.GSSCRED_GIDS_len;
2140 			res.gids.GSSCRED_GIDS_val = NULL;
2141 			res.gids.GSSCRED_GIDS_len = 0;
2142 		}
2143 	}
2144 
2145 	/* free RPC results */
2146 	clnt_freeres(clnt, xdr_gsscred_expname_to_unix_cred_res, (caddr_t)&res);
2147 
2148 	return (res.major);
2149 } /* kgsscred_expname_to_unix_cred */
2150 
2151 OM_uint32
2152 kgsscred_name_to_unix_cred(intName, mechType, uidOut, gidOut, gids,
2153 				gidsLen, uid)
2154 	const gss_name_t intName;
2155 	const gss_OID mechType;
2156 	uid_t *uidOut;
2157 	gid_t *gidOut;
2158 	gid_t *gids[];
2159 	int *gidsLen;
2160 	uid_t uid;
2161 {
2162 	gsscred_name_to_unix_cred_arg args;
2163 	gsscred_name_to_unix_cred_res res;
2164 	OM_uint32 major, minor;
2165 	gss_OID nameOid;
2166 	gss_buffer_desc flatName = GSS_C_EMPTY_BUFFER;
2167 
2168 
2169 	/* check the input/output parameters */
2170 	if (intName == NULL || mechType == NULL)
2171 		return (GSS_S_CALL_INACCESSIBLE_READ);
2172 
2173 	if (uidOut == NULL)
2174 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
2175 
2176 	/* NULL out the output parameters */
2177 	*uidOut = 0;
2178 	if (gids)
2179 		*gids = NULL;
2180 
2181 	if (gidsLen)
2182 		*gidsLen = 0;
2183 
2184 	/* get the client handle to gssd */
2185 	if ((clnt = getgssd_handle()) == NULL)
2186 	{
2187 		clnt_pcreateerror(server);
2188 		return (GSS_S_FAILURE);
2189 	}
2190 
2191 	/* convert the name to flat representation */
2192 	if ((major = gss_display_name(&minor, intName, &flatName, &nameOid))
2193 			!= GSS_S_COMPLETE)
2194 	{
2195 		return (major);
2196 	}
2197 
2198 	/* set the rpc parameters */
2199 	args.uid = uid;
2200 	args.pname.GSS_BUFFER_T_len = flatName.length;
2201 	args.pname.GSS_BUFFER_T_val = flatName.value;
2202 	args.name_type.GSS_OID_len = nameOid->length;
2203 	args.name_type.GSS_OID_val = nameOid->elements;
2204 	args.mech_type.GSS_OID_len = mechType->length;
2205 	args.mech_type.GSS_OID_val = mechType->elements;
2206 
2207 	/* call the remote procedure */
2208 	memset(&res, 0, sizeof (res));
2209 	if (gsscred_name_to_unix_cred_1(&args, &res, clnt) != RPC_SUCCESS)
2210 	{
2211 		gss_release_buffer(&minor, &flatName);
2212 		return (GSS_S_FAILURE);
2213 	}
2214 
2215 	gss_release_buffer(&minor, &flatName);
2216 	/* copy the output parameters on output */
2217 	if (res.major == GSS_S_COMPLETE)
2218 	{
2219 		*uidOut = res.uid;
2220 		if (gidOut)
2221 			*gidOut = res.gid;
2222 		if (gids && gidsLen)
2223 		{
2224 			*gids = res.gids.GSSCRED_GIDS_val;
2225 			*gidsLen = res.gids.GSSCRED_GIDS_len;
2226 			res.gids.GSSCRED_GIDS_val = NULL;
2227 			res.gids.GSSCRED_GIDS_len = 0;
2228 		}
2229 	}
2230 
2231 	/* delete RPC allocated memory */
2232 	clnt_freeres(clnt, xdr_gsscred_name_to_unix_cred_res, (caddr_t)&res);
2233 
2234 	return (res.major);
2235 } /* kgsscred_name_to_unix_cred */
2236 
2237 OM_uint32
2238 kgss_get_group_info(puid, gidOut, gids, gidsLen, uid)
2239 	const uid_t puid;
2240 	gid_t *gidOut;
2241 	gid_t *gids[];
2242 	int *gidsLen;
2243 	uid_t uid;
2244 {
2245 	gss_get_group_info_arg args;
2246 	gss_get_group_info_res res;
2247 
2248 
2249 	/* check the output parameters */
2250 	if (gidOut == NULL || gids == NULL || gidsLen == NULL)
2251 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
2252 
2253 	/* get the client GSSD handle */
2254 	if ((clnt = getgssd_handle()) == NULL)
2255 	{
2256 		clnt_pcreateerror(server);
2257 		return (GSS_S_FAILURE);
2258 	}
2259 
2260 	/* set the input parameters */
2261 	args.uid = uid;
2262 	args.puid = puid;
2263 
2264 
2265 	/* call the remote procedure */
2266 	memset(&res, 0, sizeof (res));
2267 	if (gss_get_group_info_1(&args, &res, clnt) != RPC_SUCCESS)
2268 	{
2269 		return (GSS_S_FAILURE);
2270 	}
2271 
2272 	/* copy the results */
2273 	if (res.major == GSS_S_COMPLETE)
2274 	{
2275 		*gidOut = res.gid;
2276 		*gids = res.gids.GSSCRED_GIDS_val;
2277 		*gidsLen = res.gids.GSSCRED_GIDS_len;
2278 		res.gids.GSSCRED_GIDS_val = NULL;
2279 		res.gids.GSSCRED_GIDS_len = 0;
2280 	}
2281 
2282 	/* nothing to free */
2283 
2284 	return (res.major);
2285 } /* kgss_get_group_info */
2286 
2287 OM_uint32
2288 kgss_export_sec_context_wrapped(minor_status,
2289 				context_handle,
2290 				output_token,
2291 				gssd_context_verifier)
2292 	OM_uint32 *minor_status;
2293 	gssd_ctx_id_t *context_handle;
2294 	gss_buffer_t output_token;
2295 	OM_uint32 gssd_context_verifier;
2296 {
2297 	CLIENT *clnt;
2298 	gss_export_sec_context_arg arg;
2299 	gss_export_sec_context_res res;
2300 
2301 
2302 /* get the client handle to GSSD */
2303 
2304 	if ((clnt = getgssd_handle()) == NULL) {
2305 		clnt_pcreateerror(server);
2306 		return (GSS_S_FAILURE);
2307 	}
2308 
2309 /* copy the procedure arguments into the rpc arg parameter */
2310 
2311 	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
2312 	arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle;
2313 	arg.gssd_context_verifier = gssd_context_verifier;
2314 
2315 /* call the remote procedure */
2316 
2317 	memset(&res, 0, sizeof (res));
2318 	if (gss_export_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
2319 
2320 /*
2321  * if the RPC call times out, null out all return arguments, set minor_status
2322  * to its maximum value, and return GSS_S_FAILURE
2323  */
2324 
2325 		if (minor_status != NULL)
2326 			*minor_status = DEFAULT_MINOR_STAT;
2327 		if (context_handle != NULL)
2328 			*context_handle = NULL;
2329 		if (output_token != NULL)
2330 			output_token->length = 0;
2331 
2332 		return (GSS_S_FAILURE);
2333 	}
2334 
2335 /* copy the rpc results into the return arguments */
2336 
2337 	if (minor_status != NULL)
2338 		*minor_status = res.minor_status;
2339 
2340 	if (res.context_handle.GSS_CTX_ID_T_len == 0)
2341 		*context_handle = NULL;
2342 	else
2343 		*context_handle =
2344 		    *((gssd_ctx_id_t *)res.context_handle.GSS_CTX_ID_T_val);
2345 
2346 	if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) {
2347 		output_token->length = res.output_token.GSS_BUFFER_T_len;
2348 		output_token->value =
2349 			(void *) MALLOC(output_token->length);
2350 		memcpy(output_token->value,
2351 			res.output_token.GSS_BUFFER_T_val,
2352 			output_token->length);
2353 	}
2354 
2355 /*
2356  * free the memory allocated for the results and return with the status
2357  * received in the rpc call
2358  */
2359 
2360 	clnt_freeres(clnt, xdr_gss_export_sec_context_res, (caddr_t)&res);
2361 	return (res.status);
2362 
2363 }
2364 
2365 OM_uint32
2366 kgss_export_sec_context(minor_status,
2367 			context_handle,
2368 			output_token)
2369 	OM_uint32 *minor_status;
2370 	gss_ctx_id_t *context_handle;
2371 	gss_buffer_t output_token;
2372 {
2373 	OM_uint32 err;
2374 	struct kgss_ctx *kctx;
2375 
2376 	if (*context_handle == GSS_C_NO_CONTEXT) {
2377 		return (GSS_S_NO_CONTEXT);
2378 	} else
2379 		kctx = KCTX_TO_KGSS_CTX(*context_handle);
2380 
2381 	err = kgss_export_sec_context_wrapped(minor_status,
2382 		&kctx->gssd_ctx, output_token,
2383 		kctx->gssd_ctx_verifier);
2384 
2385 	if (GSS_ERROR(err))
2386 		return (err);
2387 	else {
2388 		KGSS_FREE(kctx);
2389 		*context_handle = GSS_C_NO_CONTEXT;
2390 		return (err);
2391 	}
2392 
2393 }
2394 
2395 OM_uint32
2396 kgss_import_sec_context_wrapped(minor_status,
2397 			input_token,
2398 			context_handle,
2399 			gssd_context_verifier)
2400 	OM_uint32 *minor_status;
2401 	gss_buffer_t input_token;
2402 	gss_ctx_id_t *context_handle;
2403 	OM_uint32 gssd_context_verifier;
2404 {
2405 	CLIENT *clnt;
2406 	gss_import_sec_context_arg arg;
2407 	gss_import_sec_context_res res;
2408 
2409 
2410 /* get the client handle to GSSD */
2411 
2412 	if ((clnt = getgssd_handle()) == NULL) {
2413 		clnt_pcreateerror(server);
2414 		return (GSS_S_FAILURE);
2415 	}
2416 
2417 /* copy the procedure arguments into the rpc arg parameter */
2418 	arg.input_token.GSS_BUFFER_T_len = (uint_t)
2419 		(input_token != GSS_C_NO_BUFFER ? input_token->length : 0);
2420 	arg.input_token.GSS_BUFFER_T_val = (char *)
2421 		(input_token != GSS_C_NO_BUFFER ? input_token->value : 0);
2422 	arg.gssd_context_verifier = gssd_context_verifier;
2423 
2424 
2425 /* call the remote procedure */
2426 
2427 	memset(&res, 0, sizeof (res));
2428 	if (gss_import_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
2429 
2430 /*
2431  * if the RPC call times out, null out all return arguments, set minor_status
2432  * to its maximum value, and return GSS_S_FAILURE
2433  */
2434 
2435 		if (minor_status != NULL)
2436 			*minor_status = DEFAULT_MINOR_STAT;
2437 		if (context_handle != NULL)
2438 			*context_handle = NULL;
2439 
2440 		return (GSS_S_FAILURE);
2441 	}
2442 
2443 /* copy the rpc results into the return arguments */
2444 
2445 	if (minor_status != NULL)
2446 		*minor_status = res.minor_status;
2447 
2448 	if (res.context_handle.GSS_CTX_ID_T_len == 0)
2449 		*context_handle = NULL;
2450 	else
2451 		*context_handle =
2452 		    *((gss_ctx_id_t *)res.context_handle.GSS_CTX_ID_T_val);
2453 
2454 
2455 /*
2456  * free the memory allocated for the results and return with the status
2457  * received in the rpc call
2458  */
2459 
2460 	clnt_freeres(clnt, xdr_gss_import_sec_context_res, (caddr_t)&res);
2461 	return (res.status);
2462 }
2463 
2464 OM_uint32
2465 kgss_import_sec_context(minor_status,
2466 			input_token,
2467 			context_handle)
2468 	OM_uint32 *minor_status;
2469 	gss_buffer_t input_token;
2470 	gss_ctx_id_t *context_handle;
2471 {
2472 	struct kgss_ctx *kctx;
2473 
2474 	if (*context_handle == GSS_C_NO_CONTEXT) {
2475 		kctx = KGSS_ALLOC();
2476 		*context_handle = (gss_ctx_id_t)kctx;
2477 		kctx->gssd_ctx = (OM_uint32) GSS_C_NO_CONTEXT;
2478 	} else
2479 		kctx = (struct kgss_ctx *)*context_handle;
2480 	return (kgss_import_sec_context_wrapped(minor_status,
2481 		input_token, &kctx->gssd_ctx,
2482 		KCTX_TO_CTXV(context_handle)));
2483 }
2484 
2485 #ifdef _KERNEL
2486 #include <sys/modctl.h>
2487 
2488 static void *gss_clnt = NULL;
2489 
2490 #ifdef DEBUG
2491 typedef struct {
2492 	char		*name;		/* just put something here */
2493 } gssd_devstate_t;
2494 
2495 
2496 static void *gssd_state;
2497 
2498 static int gssd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2499 {
2500 	/*	 cmn_err(CE_NOTE, "In gssd_attach"); */
2501 	switch (cmd) {
2502 	case DDI_ATTACH:
2503 		if (ddi_create_minor_node(dip, "gssd", S_IFCHR, 0, "gssd", 0)
2504 		    == DDI_FAILURE) {
2505 			ddi_remove_minor_node(dip, NULL);
2506 			return (DDI_FAILURE);
2507 		}
2508 		return (DDI_SUCCESS);
2509 
2510 	default:
2511 		return (DDI_FAILURE);
2512 	}
2513 }
2514 
2515 static int gssd_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd,
2516 		void *arg, void **result)
2517 {
2518 	dev_t dev;
2519 	int error;
2520 
2521 /*	 cmn_err(CE_NOTE, "In gssd_getinfo"); */
2522 
2523 	switch (infocmd) {
2524 	case DDI_INFO_DEVT2INSTANCE:
2525 		dev = (dev_t)arg;
2526 		*result = (void *) getminor(dev);
2527 		error = DDI_SUCCESS;
2528 		break;
2529 
2530 	case DDI_INFO_DEVT2DEVINFO:
2531 	/*	cmn_err(CE_NOTE, "getinfo wants devinfo"); */
2532 	default:
2533 		error = DDI_FAILURE;
2534 		break;
2535 	}
2536 	return (error);
2537 }
2538 
2539 static int gssd_identify(dev_info_t *dip)
2540 {
2541 	/*	 cmn_err(CE_NOTE, "in gssd_identify"); */
2542 	if (strcmp(ddi_get_name(dip), "gssd") == 0)
2543 		return (DDI_IDENTIFIED);
2544 	else
2545 		return (DDI_NOT_IDENTIFIED);
2546 }
2547 
2548 static int gssd_probe(dev_info_t *dip)
2549 {
2550 	/*	 cmn_err(CE_NOTE, "In gssd_probe"); */
2551 
2552 	return (DDI_PROBE_SUCCESS);
2553 }
2554 
2555 static int gssd_open(dev_t *devp, int flag, int otyp, cred_t *credp)
2556 {
2557 	/*	 cmn_err (CE_NOTE, "In gssd_open"); */
2558 	if (otyp != OTYP_CHR)
2559 		return (EINVAL);
2560 
2561 	gss_clnt = getgssd_handle();
2562 	return (0);
2563 }
2564 
2565 static int gssd_close(dev_t dev, int flag, int otyp, cred_t *credp)
2566 {
2567 	/*	 cmn_err(CE_NOTE, "In gssd_close"); */
2568 	killgssd_handle(gss_clnt);
2569 	return (0);
2570 }
2571 
2572 static int gssd_write(dev_t dev, struct uio *uiop, cred_t *credp)
2573 {
2574 	char buffer[1024];
2575 	int len;
2576 
2577 	/*	 cmn_err(CE_NOTE, "In gssd_write"); */
2578 	bzero(buffer, 1024);
2579 
2580 	uiomove(buffer, 1024, UIO_WRITE, uiop);
2581 	len = strlen(buffer);
2582 
2583 	if (buffer[len-1] == '\n')
2584 		buffer[--len] = '\0';
2585 
2586 	cmn_err(CE_NOTE, "Got command: (%d) \"%s\"", len, buffer);
2587 	do_gssdtest(buffer);
2588 	return (0);
2589 }
2590 
2591 static struct cb_ops gssd_cb_ops = {
2592 	gssd_open,		/* cb_open */
2593 	gssd_close,		/* cb_close */
2594 	nodev,			/* cb_strategy */
2595 	nodev,			/* cb_print */
2596 	nodev,			/* cb_dump */
2597 	nulldev,		/* cb_read */
2598 	gssd_write,		/* cb_write */
2599 	nodev,			/* cb_ioctl */
2600 	nodev,			/* cb_devmap */
2601 	nodev,			/* cb_mmap */
2602 	nodev,			/* cb_segmap */
2603 	nochpoll,		/* cb_chpoll */
2604 	ddi_prop_op,		/* cb_prop_op */
2605 	NULL,			/* cb_stream */
2606 	(int)(D_NEW|D_MP)	/* cb_flag */
2607 };
2608 
2609 static struct dev_ops gssd_ops = {
2610 	DEVO_REV,		/* devo_rev */
2611 	0,			/* devo_refcnt */
2612 	gssd_getinfo,		/* devo_getinfo */
2613 	gssd_identify,		/* devo_identify */
2614 	nulldev,		/* devo_probe */
2615 	gssd_attach,		/* devo_attach */
2616 	nulldev,		/* devo_detach */
2617 	nodev,			/* devo_reset */
2618 	&gssd_cb_ops,		/* devo_cb_ops */
2619 	(struct bus_ops *)NULL	/* devo_bus_ops */
2620 };
2621 
2622 extern struct mod_ops mod_driverops;
2623 
2624 static struct modldrv modlmisc = {
2625 	&mod_driverops,
2626 	"GSSD DRV Client Module",
2627 	&gssd_ops
2628 
2629 #else /* !DEBUG */
2630 
2631 static struct modlmisc modlmisc = {
2632 	&mod_miscops,
2633 	"GSSD Client Module"
2634 #endif /* DEBUG */
2635 };
2636 
2637 static struct modlinkage modlinkage = {
2638 	MODREV_1,
2639 	(void *)&modlmisc,
2640 	NULL
2641 };
2642 
2643 char _depends_on[] = "strmod/rpcmod misc/tlimod";
2644 
2645 _init(void)
2646 {
2647 	int status;
2648 
2649 	if ((status = ddi_soft_state_init(&gssd_state,
2650 	    sizeof (gssd_devstate_t), 1)) != 0)
2651 		return (status);
2652 
2653 	if ((status = mod_install((struct modlinkage *)&modlinkage)) != 0)
2654 		ddi_soft_state_fini(&gssd_state);
2655 
2656 	cmn_err(CE_NOTE, "gssd: I'm in the kernel: %d.", status);
2657 	return (status);
2658 }
2659 
2660 _fini()
2661 {
2662 	int status;
2663 
2664 	killgssd_handle(gss_clnt);
2665 	cmn_err(CE_NOTE, "gssd: Handle destroyed.. leaving module.");
2666 
2667 	if ((status = mod_remove(&modlinkage)) != 0)
2668 		return (status);
2669 
2670 	ddi_soft_state_fini(&gssd_state);
2671 	return (status);
2672 }
2673 
2674 _info(modinfop)
2675 struct modinfo *modinfop;
2676 {
2677 	return (mod_info(&modlinkage, modinfop));
2678 }
2679 
2680 #endif
2681