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