xref: /illumos-gate/usr/src/cmd/gss/gssd/gssd_proc.c (revision ba7b222e36bac28710a7f43739283302b617e7f5)
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  *  RPC server procedures for the gssapi usermode daemon gssd.
28  */
29 
30 #include <stdio.h>
31 #include <stdio_ext.h>
32 #include <unistd.h>
33 #include <pwd.h>
34 #include <grp.h>
35 #include <strings.h>
36 #include <limits.h>
37 #include <sys/param.h>
38 #include <sys/syslog.h>
39 #include <mechglueP.h>
40 #include "gssd.h"
41 #include <gssapi/gssapi.h>
42 #include <rpc/rpc.h>
43 #include <stdlib.h>
44 #include <syslog.h>
45 #include <sys/resource.h>
46 
47 #define	SRVTAB	""
48 #define	FDCACHE_PERCENTAGE	.75	/* Percentage of total FD limit */
49 #define	FDCACHE_DEFAULT		16	/* Default LRU cache size */
50 #define	GSSD_FD_LIMIT		255	/* Increase number of fds allowed */
51 
52 extern int gssd_debug;			/* declared in gssd.c */
53 static OM_uint32 gssd_time_verf;	/* verifies same gssd */
54 static OM_uint32 context_verf;		/* context sequence numbers */
55 
56 struct gssd_ctx_slot {
57 	struct gssd_ctx_slot *lru_next;
58 	struct gssd_ctx_slot *lru_prev;
59 	bool_t		inuse;
60 	OM_uint32	create_time;
61 	OM_uint32	verf;
62 	gss_ctx_id_t	ctx;
63 	gss_ctx_id_t	rpcctx;
64 };
65 
66 struct gssd_ctx_slot *gssd_ctx_slot_tbl;
67 struct gssd_ctx_slot *gssd_lru_head;
68 
69 static int max_contexts;
70 
71 static int checkfrom(struct svc_req *, uid_t *);
72 extern void set_gssd_uid(uid_t);
73 extern int __rpc_get_local_uid(SVCXPRT *, uid_t *);
74 
75 void
76 gssd_setup(char *arg)
77 {
78 	int i;
79 	struct rlimit rl;
80 	hrtime_t high_res_time;
81 
82 	gssd_time_verf = (OM_uint32)time(NULL);
83 	max_contexts = FDCACHE_DEFAULT;
84 
85 	/*
86 	 * Use low order bits of high resolution time to get a reasonably
87 	 * random number to start the context sequencing.  This alternative
88 	 * to using a time value avoid clock resets via NTP or ntpdate.
89 	 */
90 	high_res_time = gethrtime();
91 	context_verf = (OM_uint32)high_res_time;
92 
93 	/*
94 	 * Increase resource limit of FDs in case we get alot accept/init_
95 	 * sec_context calls before we're able to export them.  This can
96 	 * happen in very heavily load environments where gssd doesn't get
97 	 * much time to work on its backlog.
98 	 */
99 	if ((getrlimit(RLIMIT_NOFILE, &rl)) == 0) {
100 		rl.rlim_cur = (rl.rlim_max >= GSSD_FD_LIMIT) ?
101 				GSSD_FD_LIMIT : rl.rlim_max;
102 		if ((setrlimit(RLIMIT_NOFILE, &rl)) == 0)
103 			max_contexts = rl.rlim_cur * FDCACHE_PERCENTAGE;
104 		(void) enable_extended_FILE_stdio(-1, -1);
105 	}
106 
107 	gssd_ctx_slot_tbl = (struct gssd_ctx_slot *)
108 		malloc(sizeof (struct gssd_ctx_slot) * max_contexts);
109 
110 	if (gssd_ctx_slot_tbl == NULL) {
111 		(void) fprintf(stderr,
112 			gettext("[%s] could not allocate %d byte context table"
113 			"\n"), arg,
114 			(sizeof (struct gssd_ctx_slot) * max_contexts));
115 		exit(1);
116 	}
117 
118 	for (i = 1; i < max_contexts; i++) {
119 		gssd_ctx_slot_tbl[i-1].lru_next = &gssd_ctx_slot_tbl[i];
120 		gssd_ctx_slot_tbl[i].lru_prev = &gssd_ctx_slot_tbl[i-1];
121 		gssd_ctx_slot_tbl[i].inuse = FALSE;
122 		gssd_ctx_slot_tbl[i].verf = 0;
123 		gssd_ctx_slot_tbl[i].create_time = 0;
124 		gssd_ctx_slot_tbl[i].rpcctx = (gss_ctx_id_t)(i + 1);
125 	}
126 
127 	gssd_ctx_slot_tbl[max_contexts - 1].lru_next = &gssd_ctx_slot_tbl[0];
128 	gssd_ctx_slot_tbl[0].lru_prev = &gssd_ctx_slot_tbl[max_contexts - 1];
129 	gssd_ctx_slot_tbl[0].inuse = FALSE;
130 	gssd_ctx_slot_tbl[0].verf = 0;
131 	gssd_ctx_slot_tbl[0].create_time = 0;
132 	gssd_ctx_slot_tbl[0].rpcctx = (gss_ctx_id_t)1;
133 
134 	gssd_lru_head = &gssd_ctx_slot_tbl[0];
135 }
136 
137 static OM_uint32 syslog_interval = 60;
138 
139 static struct gssd_ctx_slot *
140 gssd_alloc_slot(gss_ctx_id_t ctx)
141 {
142 	struct gssd_ctx_slot *lru;
143 	OM_uint32 current_time;
144 	static OM_uint32 last_syslog = 0;
145 	static bool_t first_take = TRUE;
146 	static int tooks;
147 	OM_uint32 minor_status;
148 
149 	lru = gssd_lru_head;
150 	gssd_lru_head = lru->lru_next;
151 
152 	current_time = (OM_uint32) time(NULL);
153 
154 	if (last_syslog == 0)
155 		last_syslog = current_time;	/* Save 1st alloc time */
156 
157 	if (lru->inuse) {
158 		if (lru->ctx != GSS_C_NO_CONTEXT)
159 			(void) gss_delete_sec_context(&minor_status,
160 				&lru->ctx, NULL);
161 		tooks++;
162 
163 		if (((current_time - last_syslog) > syslog_interval) ||
164 			first_take) {
165 			syslog(LOG_WARNING, gettext("re-used an existing "
166 				"context slot of age %u seconds (%d slots re-"
167 				"used during last %u seconds)"),
168 				current_time - lru->create_time, tooks,
169 				current_time - last_syslog);
170 
171 			last_syslog = current_time;
172 			tooks = 0;
173 			first_take = FALSE;
174 		}
175 	}
176 
177 	/*
178 	 * Assign the next context verifier to the context (avoiding zero).
179 	 */
180 	context_verf++;
181 	if (context_verf == 0)
182 		context_verf = 1;
183 	lru->verf = context_verf;
184 
185 	lru->create_time = current_time;
186 	lru->ctx = ctx;
187 	lru->inuse = TRUE;
188 	return (lru);
189 }
190 
191 /*
192  * We always add 1 because we don't want slot 0 to be confused
193  * with GSS_C_NO_CONTEXT.
194  */
195 
196 static struct gssd_ctx_slot *
197 gssd_handle_to_slot(GSS_CTX_ID_T *h)
198 {
199 	intptr_t i;
200 
201 	if (h->GSS_CTX_ID_T_len == 0) {
202 		return (NULL);
203 	}
204 	if (h->GSS_CTX_ID_T_len != sizeof (i))
205 		return (NULL);
206 
207 	i = (*(intptr_t *)(h->GSS_CTX_ID_T_val)) - 1;
208 
209 	if (i < 0 || i >= max_contexts)
210 		return (NULL);
211 
212 	return (&gssd_ctx_slot_tbl[i]);
213 }
214 
215 static void
216 gssd_rel_slot(struct gssd_ctx_slot *lru)
217 {
218 	struct gssd_ctx_slot *prev, *next;
219 
220 	if (lru == NULL)
221 		return;
222 
223 	lru->inuse = FALSE;
224 
225 	/*
226 	 * Remove entry from its current location in list
227 	 */
228 	prev = lru->lru_prev;
229 	next = lru->lru_next;
230 	prev->lru_next = next;
231 	next->lru_prev = prev;
232 
233 	/*
234 	 * Since it is no longer in use, it is the least recently
235 	 * used.
236 	 */
237 	prev = gssd_lru_head->lru_prev;
238 	next = gssd_lru_head;
239 
240 	prev->lru_next = lru;
241 	lru->lru_prev = prev;
242 
243 	next->lru_prev = lru;
244 	lru->lru_next = next;
245 
246 	gssd_lru_head = lru;
247 }
248 
249 static void
250 gssd_convert_context_handle(GSS_CTX_ID_T *h,
251 	gss_ctx_id_t *context_handle,
252 	OM_uint32 verf,
253 	bool_t *context_verf_ok,
254 	struct gssd_ctx_slot **slotp)
255 {
256 	struct gssd_ctx_slot *slot;
257 
258 	*context_verf_ok = FALSE;
259 	*context_handle = (gss_ctx_id_t)1;
260 	if (slotp != NULL)
261 		*slotp = NULL;
262 
263 	if (h->GSS_CTX_ID_T_len == 0) {
264 		*context_handle = GSS_C_NO_CONTEXT;
265 		*context_verf_ok = TRUE;
266 		return;
267 	}
268 
269 	slot = gssd_handle_to_slot(h);
270 
271 	if (slot == NULL)
272 		return;
273 
274 	if (verf != slot->verf)
275 		return;
276 
277 	*context_verf_ok = TRUE;
278 	*context_handle = slot->ctx;
279 	if (slotp != NULL)
280 		*slotp = slot;
281 }
282 
283 bool_t
284 gss_acquire_cred_1_svc(argp, res, rqstp)
285 	gss_acquire_cred_arg *argp;
286 	gss_acquire_cred_res *res;
287 	struct svc_req *rqstp;
288 {
289 	OM_uint32 		minor_status;
290 	gss_name_t		desired_name;
291 	gss_OID_desc		name_type_desc;
292 	gss_OID			name_type = &name_type_desc;
293 	OM_uint32		time_req;
294 	gss_OID_set_desc	desired_mechs_desc;
295 	gss_OID_set		desired_mechs;
296 	int			cred_usage;
297 	gss_cred_id_t 		output_cred_handle;
298 	gss_OID_set 		actual_mechs;
299 	gss_buffer_desc		external_name;
300 	uid_t			uid;
301 	int			i, j;
302 
303 	if (gssd_debug)
304 		fprintf(stderr, gettext("gss_acquire_cred\n"));
305 
306 	memset(res, 0, sizeof (*res));
307 
308 	/*
309 	 * if the request isn't from root, null out the result pointer
310 	 * entries, so the next time through xdr_free won't try to
311 	 * free unmalloc'd memory and then return NULL
312 	 */
313 
314 	if (checkfrom(rqstp, &uid) == 0) {
315 		res->output_cred_handle.GSS_CRED_ID_T_val = NULL;
316 		res->actual_mechs.GSS_OID_SET_val = NULL;
317 		return (FALSE);
318 	}
319 
320 /* set the uid sent as the RPC argument */
321 
322 	uid = argp->uid;
323 	set_gssd_uid(uid);
324 
325 /* convert the desired name from external to internal format */
326 
327 	external_name.length = argp->desired_name.GSS_BUFFER_T_len;
328 	external_name.value = (void *)malloc(external_name.length);
329 	if (!external_name.value)
330 		return (GSS_S_FAILURE);
331 	memcpy(external_name.value, argp->desired_name.GSS_BUFFER_T_val,
332 		external_name.length);
333 
334 	if (argp->name_type.GSS_OID_len == 0) {
335 		name_type = GSS_C_NULL_OID;
336 	} else {
337 		name_type->length = argp->name_type.GSS_OID_len;
338 		name_type->elements = (void *)malloc(name_type->length);
339 		if (!name_type->elements) {
340 			free(external_name.value);
341 			return (GSS_S_FAILURE);
342 		}
343 		memcpy(name_type->elements, argp->name_type.GSS_OID_val,
344 			name_type->length);
345 	}
346 
347 	if (gss_import_name(&minor_status, &external_name, name_type,
348 			    &desired_name) != GSS_S_COMPLETE) {
349 
350 		res->status = (OM_uint32) GSS_S_FAILURE;
351 		res->minor_status = minor_status;
352 
353 		free(external_name.value);
354 		if (name_type != GSS_C_NULL_OID)
355 			free(name_type->elements);
356 
357 		return (TRUE);
358 	}
359 
360 /*
361  * copy the XDR structured arguments into their corresponding local GSSAPI
362  * variables.
363  */
364 
365 	cred_usage = argp->cred_usage;
366 	time_req = argp->time_req;
367 
368 	if (argp->desired_mechs.GSS_OID_SET_len != 0) {
369 		desired_mechs = &desired_mechs_desc;
370 		desired_mechs->count =
371 			(int)argp->desired_mechs.GSS_OID_SET_len;
372 		desired_mechs->elements = (gss_OID)
373 			malloc(sizeof (gss_OID_desc) * desired_mechs->count);
374 		if (!desired_mechs->elements) {
375 			free(external_name.value);
376 			free(name_type->elements);
377 			return (GSS_S_FAILURE);
378 		}
379 		for (i = 0; i < desired_mechs->count; i++) {
380 			desired_mechs->elements[i].length =
381 				(OM_uint32)argp->desired_mechs.
382 				GSS_OID_SET_val[i].GSS_OID_len;
383 			desired_mechs->elements[i].elements =
384 				(void *)malloc(desired_mechs->elements[i].
385 						length);
386 			if (!desired_mechs->elements[i].elements) {
387 				free(external_name.value);
388 				free(name_type->elements);
389 				for (j = 0; j < (i -1); j++) {
390 					free
391 					(desired_mechs->elements[j].elements);
392 				}
393 				free(desired_mechs->elements);
394 				return (GSS_S_FAILURE);
395 			}
396 			memcpy(desired_mechs->elements[i].elements,
397 				argp->desired_mechs.GSS_OID_SET_val[i].
398 				GSS_OID_val,
399 				desired_mechs->elements[i].length);
400 		}
401 	} else
402 		desired_mechs = GSS_C_NULL_OID_SET;
403 
404 	/* call the gssapi routine */
405 
406 	res->status = (OM_uint32)gss_acquire_cred(&res->minor_status,
407 				desired_name,
408 				time_req,
409 				desired_mechs,
410 				cred_usage,
411 				&output_cred_handle,
412 				&actual_mechs,
413 				&res->time_rec);
414 
415 	/*
416 	 * convert the output args from the parameter given in the call to the
417 	 * variable in the XDR result
418 	 */
419 
420 	res->output_cred_handle.GSS_CRED_ID_T_len = sizeof (gss_cred_id_t);
421 	res->output_cred_handle.GSS_CRED_ID_T_val =
422 		(void *)malloc(sizeof (gss_cred_id_t));
423 	if (!res->output_cred_handle.GSS_CRED_ID_T_val) {
424 		free(external_name.value);
425 		free(name_type->elements);
426 		for (i = 0; i < desired_mechs->count; i++) {
427 			free(desired_mechs->elements[i].elements);
428 			}
429 		free(desired_mechs->elements);
430 		return (GSS_S_FAILURE);
431 	}
432 	memcpy(res->output_cred_handle.GSS_CRED_ID_T_val, &output_cred_handle,
433 		sizeof (gss_cred_id_t));
434 
435 	if (actual_mechs != GSS_C_NULL_OID_SET) {
436 		res->actual_mechs.GSS_OID_SET_len =
437 			(uint_t)actual_mechs->count;
438 		res->actual_mechs.GSS_OID_SET_val = (GSS_OID *)
439 			malloc(sizeof (GSS_OID) * actual_mechs->count);
440 		if (!res->actual_mechs.GSS_OID_SET_val) {
441 			free(external_name.value);
442 			free(name_type->elements);
443 			for (i = 0; i < desired_mechs->count; i++) {
444 				free(desired_mechs->elements[i].elements);
445 			}
446 			free(desired_mechs->elements);
447 			free(res->output_cred_handle.GSS_CRED_ID_T_val);
448 			return (GSS_S_FAILURE);
449 		}
450 		for (i = 0; i < actual_mechs->count; i++) {
451 			res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_len =
452 				(uint_t)actual_mechs->elements[i].length;
453 			res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val =
454 				(char *)malloc(actual_mechs->elements[i].
455 						length);
456 			if (!res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val) {
457 				free(external_name.value);
458 				free(name_type->elements);
459 				free(desired_mechs->elements);
460 				for (j = 0; j < desired_mechs->count; j++) {
461 					free
462 					(desired_mechs->elements[i].elements);
463 				}
464 				free(res->actual_mechs.GSS_OID_SET_val);
465 				for (j = 0; j < (i - 1); j++) {
466 					free
467 					(res->actual_mechs.
468 						GSS_OID_SET_val[j].GSS_OID_val);
469 				}
470 				return (GSS_S_FAILURE);
471 			}
472 			memcpy(res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val,
473 				actual_mechs->elements[i].elements,
474 				actual_mechs->elements[i].length);
475 		}
476 	} else
477 		res->actual_mechs.GSS_OID_SET_len = 0;
478 
479 	/*
480 	 * set the time verifier for credential handle.  To ensure that the
481 	 * timestamp is not the same as previous gssd process, verify that
482 	 * time is not the same as set earlier at start of process.  If it
483 	 * is, sleep one second and reset. (due to one second granularity)
484 	 */
485 
486 	if (res->status == GSS_S_COMPLETE) {
487 		res->gssd_cred_verifier = (OM_uint32)time(NULL);
488 		if (res->gssd_cred_verifier == gssd_time_verf) {
489 			sleep(1);
490 			gssd_time_verf = (OM_uint32)time(NULL);
491 		}
492 		res->gssd_cred_verifier = gssd_time_verf;
493 	}
494 
495 	/*
496 	 * now release the space allocated by the underlying gssapi mechanism
497 	 * library for actual_mechs as well as by this routine for
498 	 * external_name, name_type and desired_name
499 	 */
500 
501 	free(external_name.value);
502 	if (name_type != GSS_C_NULL_OID)
503 		free(name_type->elements);
504 	gss_release_name(&minor_status, &desired_name);
505 
506 	if (actual_mechs != GSS_C_NULL_OID_SET) {
507 		for (i = 0; i < actual_mechs->count; i++)
508 			free(actual_mechs->elements[i].elements);
509 		free(actual_mechs->elements);
510 		free(actual_mechs);
511 	}
512 
513 	if (desired_mechs != GSS_C_NULL_OID_SET) {
514 		for (i = 0; i < desired_mechs->count; i++)
515 			free(desired_mechs->elements[i].elements);
516 		free(desired_mechs->elements);
517 
518 	}
519 
520 /* return to caller */
521 
522 	return (TRUE);
523 }
524 
525 bool_t
526 gss_add_cred_1_svc(argp, res, rqstp)
527 	gss_add_cred_arg *argp;
528 	gss_add_cred_res *res;
529 	struct svc_req *rqstp;
530 {
531 
532 	OM_uint32 		minor_status;
533 	gss_name_t		desired_name;
534 	gss_OID_desc		name_type_desc;
535 	gss_OID			name_type = &name_type_desc;
536 	gss_OID_desc		desired_mech_type_desc;
537 	gss_OID			desired_mech_type = &desired_mech_type_desc;
538 	int			cred_usage;
539 	gss_cred_id_t 		input_cred_handle;
540 	gss_OID_set 		actual_mechs;
541 	gss_buffer_desc		external_name;
542 	uid_t			uid;
543 	int			i, j;
544 
545 	if (gssd_debug)
546 		fprintf(stderr, gettext("gss_add_cred\n"));
547 
548 	if (argp->gssd_cred_verifier != gssd_time_verf) {
549 		res->status = (OM_uint32)GSS_S_DEFECTIVE_CREDENTIAL;
550 		res->minor_status = 0;
551 		res->actual_mechs.GSS_OID_SET_len = 0;
552 		res->actual_mechs.GSS_OID_SET_val = NULL;
553 		res->initiator_time_rec = 0;
554 		res->acceptor_time_rec = 0;
555 		fprintf(stderr, gettext("gss_add_cred defective cred\n"));
556 		return (TRUE);
557 	}
558 	memset(res, 0, sizeof (*res));
559 
560 	/*
561 	 * if the request isn't from root, null out the result pointer
562 	 * entries, so the next time through xdr_free won't try to
563 	 * free unmalloc'd memory and then return NULL
564 	 */
565 
566 	if (checkfrom(rqstp, &uid) == 0) {
567 		return (FALSE);
568 	}
569 
570 /* set the uid sent as the RPC argument */
571 
572 	uid = argp->uid;
573 	set_gssd_uid(uid);
574 
575 /* convert the desired name from external to internal format */
576 
577 	external_name.length = argp->desired_name.GSS_BUFFER_T_len;
578 	external_name.value = (void *)argp->desired_name.GSS_BUFFER_T_val;
579 	name_type->length = argp->name_type.GSS_OID_len;
580 	name_type->elements = (void *)argp->name_type.GSS_OID_val;
581 
582 	if (gss_import_name(&minor_status, &external_name, name_type,
583 			    &desired_name) != GSS_S_COMPLETE) {
584 
585 		if (gssd_debug)
586 			fprintf(stderr,
587 				gettext("gss_add_cred:import name"),
588 				gettext(" failed status %d \n"),
589 				res->status);
590 		res->status = (OM_uint32)GSS_S_FAILURE;
591 		res->minor_status = minor_status;
592 		return (TRUE);
593 	}
594 
595 /*
596  * copy the XDR structured arguments into their corresponding local GSSAPI
597  * variables.
598  */
599 
600 	cred_usage = argp->cred_usage;
601 	if (argp->desired_mech_type.GSS_OID_len == 0)
602 		desired_mech_type = GSS_C_NULL_OID;
603 	else {
604 		desired_mech_type->length =
605 			(OM_uint32)argp->desired_mech_type.GSS_OID_len;
606 		desired_mech_type->elements =
607 			(void *)malloc(desired_mech_type->length);
608 		if (!desired_mech_type->elements) {
609 			return (GSS_S_FAILURE);
610 		}
611 		memcpy(desired_mech_type->elements,
612 			argp->desired_mech_type.GSS_OID_val,
613 			desired_mech_type->length);
614 	}
615 	input_cred_handle =
616 		(argp->input_cred_handle.GSS_CRED_ID_T_len == 0 ?
617 			GSS_C_NO_CREDENTIAL :
618 			/*LINTED*/
619 			*((gss_cred_id_t *)argp->input_cred_handle.
620 				GSS_CRED_ID_T_val));
621 
622 	if (input_cred_handle != GSS_C_NO_CREDENTIAL)
623 	/* verify the input_cred_handle */
624 		if (argp->gssd_cred_verifier != gssd_time_verf) {
625 			res->status = (OM_uint32)GSS_S_DEFECTIVE_CREDENTIAL;
626 			res->minor_status = 0;
627 			return (TRUE);
628 		}
629 
630 	/* call the gssapi routine */
631 
632 	res->status = (OM_uint32)gss_add_cred(&res->minor_status,
633 				input_cred_handle,
634 				desired_name,
635 				desired_mech_type,
636 				cred_usage,
637 				argp->initiator_time_req,
638 				argp->acceptor_time_req,
639 				NULL,
640 				&actual_mechs,
641 				&res->initiator_time_rec,
642 				&res->acceptor_time_rec);
643 
644 	if ((res->status != GSS_S_COMPLETE) &&
645 		(res->status != GSS_S_DUPLICATE_ELEMENT) &&
646 		(gssd_debug))
647 		fprintf(stderr, gettext("gss_add_cred failed status %d \n"),
648 			res->status);
649 	/*
650 	 * convert the output args from the parameter given in the call to the
651 	 * variable in the XDR result
652 	 */
653 	if (actual_mechs != GSS_C_NULL_OID_SET) {
654 		res->actual_mechs.GSS_OID_SET_len =
655 			(uint_t)actual_mechs->count;
656 		res->actual_mechs.GSS_OID_SET_val = (GSS_OID *)
657 			malloc(sizeof (GSS_OID) * actual_mechs->count);
658 		if (!res->actual_mechs.GSS_OID_SET_val) {
659 			free(desired_mech_type->elements);
660 			free(desired_mech_type);
661 			return (GSS_S_FAILURE);
662 		}
663 		for (i = 0; i < actual_mechs->count; i++) {
664 			res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_len =
665 				(uint_t)actual_mechs->elements[i].length;
666 			res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val =
667 				(char *)malloc(actual_mechs->elements[i].
668 						length);
669 			if (!res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val) {
670 				free(desired_mech_type->elements);
671 				free(desired_mech_type);
672 				free(res->actual_mechs.GSS_OID_SET_val);
673 				for (j = 0; j < (i - 1); j++) {
674 					free
675 					(res->actual_mechs.
676 						GSS_OID_SET_val[j].GSS_OID_val);
677 				}
678 				return (GSS_S_FAILURE);
679 			}
680 			memcpy(res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val,
681 				actual_mechs->elements[i].elements,
682 				actual_mechs->elements[i].length);
683 		}
684 	} else
685 		res->actual_mechs.GSS_OID_SET_len = 0;
686 
687 	/*
688 	 * now release the space allocated for
689 	 * desired_name  and desired_mech_type
690 	 */
691 
692 	gss_release_name(&minor_status, &desired_name);
693 	free(desired_mech_type->elements);
694 	gss_release_oid_set(&minor_status, &actual_mechs);
695 	/*
696 	 * if (actual_mechs != GSS_C_NULL_OID_SET) {
697 	 * 	for (i = 0; i < actual_mechs->count; i++)
698 	 * 		free(actual_mechs->elements[i].elements);
699 	 * 	free(actual_mechs->elements);
700 	 * 	free(actual_mechs);
701 	 * }
702 	 */
703 
704 
705 /* return to caller */
706 
707 	return (TRUE);
708 }
709 
710 bool_t
711 gss_release_cred_1_svc(argp, res, rqstp)
712 gss_release_cred_arg *argp;
713 gss_release_cred_res *res;
714 struct svc_req *rqstp;
715 {
716 
717 	uid_t uid;
718 	gss_cred_id_t cred_handle;
719 
720 	memset(res, 0, sizeof (*res));
721 
722 	if (gssd_debug)
723 		fprintf(stderr, gettext("gss_release_cred\n"));
724 
725 	if (checkfrom(rqstp, &uid) == 0)
726 		return (FALSE);
727 
728 	/* set the uid sent as the RPC argument */
729 
730 	uid = argp->uid;
731 	set_gssd_uid(uid);
732 
733 	/*
734 	 * if the cred_handle verifier is not correct,
735 	 * set status to GSS_S_DEFECTIVE_CREDENTIAL and return
736 	 */
737 
738 	if (argp->gssd_cred_verifier != gssd_time_verf) {
739 		res->status = (OM_uint32)GSS_S_DEFECTIVE_CREDENTIAL;
740 		return (TRUE);
741 	}
742 
743 	/*
744 	 * if the cred_handle length is 0
745 	 * set cred_handle argument to GSS_S_NO_CREDENTIAL
746 	 */
747 
748 	if (argp->cred_handle.GSS_CRED_ID_T_len == 0)
749 		cred_handle = GSS_C_NO_CREDENTIAL;
750 	else
751 		cred_handle =
752 		(gss_cred_id_t)argp->cred_handle.GSS_CRED_ID_T_val;
753 
754 	/* call the gssapi routine */
755 
756 	res->status = (OM_uint32)gss_release_cred(&res->minor_status,
757 					&cred_handle);
758 
759 	/* return to caller */
760 
761 	return (TRUE);
762 }
763 
764 bool_t
765 gss_init_sec_context_1_svc(argp, res, rqstp)
766 gss_init_sec_context_arg *argp;
767 gss_init_sec_context_res *res;
768 struct svc_req *rqstp;
769 {
770 
771 	OM_uint32 	minor_status;
772 	gss_ctx_id_t	context_handle;
773 	bool_t context_verf_ok;
774 	gss_cred_id_t	claimant_cred_handle;
775 	gss_buffer_desc	external_name;
776 	gss_OID_desc	name_type_desc;
777 	gss_OID		name_type = &name_type_desc;
778 	gss_name_t	internal_name;
779 
780 	gss_OID_desc	mech_type_desc;
781 	gss_OID		mech_type = &mech_type_desc;
782 	struct gss_channel_bindings_struct
783 			input_chan_bindings;
784 	gss_channel_bindings_t input_chan_bindings_ptr;
785 	gss_buffer_desc input_token;
786 	gss_buffer_desc output_token;
787 	gss_buffer_t input_token_ptr;
788 	gss_OID actual_mech_type;
789 	struct gssd_ctx_slot *slot = NULL;
790 
791 	uid_t uid;
792 
793 	memset(res, 0, sizeof (*res));
794 
795 	if (gssd_debug)
796 		fprintf(stderr, gettext("gss_init_sec_context\n"));
797 
798 	/*
799 	 * if the request isn't from root, null out the result pointer
800 	 * entries, so the next time through xdr_free won't try to
801 	 * free unmalloc'd memory and then return NULL
802 	 */
803 
804 	if (checkfrom(rqstp, &uid) == 0) {
805 		res->context_handle.GSS_CTX_ID_T_val =  NULL;
806 		res->actual_mech_type.GSS_OID_val = NULL;
807 		res->output_token.GSS_BUFFER_T_val = NULL;
808 		return (FALSE);
809 	}
810 
811 /* set the uid sent as the RPC argument */
812 
813 	uid = argp->uid;
814 	set_gssd_uid(uid);
815 
816 /*
817  * copy the supplied context handle into the local context handle, so it
818  * can be supplied to the gss_init_sec_context call
819  */
820 
821 	gssd_convert_context_handle(&argp->context_handle, &context_handle,
822 		argp->gssd_context_verifier, &context_verf_ok, &slot);
823 
824 	claimant_cred_handle =
825 		(argp->claimant_cred_handle.GSS_CRED_ID_T_len == 0 ?
826 		GSS_C_NO_CREDENTIAL :
827 		/*LINTED*/
828 		*((gss_cred_id_t *)argp->claimant_cred_handle.
829 			GSS_CRED_ID_T_val));
830 
831 	if (claimant_cred_handle != GSS_C_NO_CREDENTIAL) {
832 		/* verify the verifier_cred_handle */
833 		if (argp->gssd_cred_verifier != gssd_time_verf) {
834 			res->context_handle.GSS_CTX_ID_T_val = NULL;
835 			res->output_token.GSS_BUFFER_T_val = NULL;
836 			res->actual_mech_type.GSS_OID_val = NULL;
837 			res->context_handle.GSS_CTX_ID_T_len = 0;
838 			res->output_token.GSS_BUFFER_T_len = 0;
839 			res->actual_mech_type.GSS_OID_len = 0;
840 			res->status = (OM_uint32)GSS_S_DEFECTIVE_CREDENTIAL;
841 			res->minor_status = 0;
842 			return (TRUE);
843 		}
844 	}
845 
846 	if (context_handle != GSS_C_NO_CONTEXT) {
847 		/* verify the verifier_context_handle */
848 
849 		if (!context_verf_ok) {
850 			res->context_handle.GSS_CTX_ID_T_val = NULL;
851 			res->output_token.GSS_BUFFER_T_val = NULL;
852 			res->actual_mech_type.GSS_OID_val = NULL;
853 			res->context_handle.GSS_CTX_ID_T_len = 0;
854 			res->output_token.GSS_BUFFER_T_len = 0;
855 			res->actual_mech_type.GSS_OID_len = 0;
856 			res->status = (OM_uint32)GSS_S_NO_CONTEXT;
857 			res->minor_status = 0;
858 			return (TRUE);
859 		}
860 	}
861 
862 	/* convert the target name from external to internal format */
863 
864 	external_name.length = argp->target_name.GSS_BUFFER_T_len;
865 	external_name.value = (void *)argp->target_name.GSS_BUFFER_T_val;
866 
867 	if (argp->name_type.GSS_OID_len == 0) {
868 		name_type = GSS_C_NULL_OID;
869 	} else {
870 		name_type->length = argp->name_type.GSS_OID_len;
871 		name_type->elements = (void *)malloc(name_type->length);
872 		if (!name_type->elements)
873 			return (GSS_S_FAILURE);
874 		memcpy(name_type->elements, argp->name_type.GSS_OID_val,
875 			name_type->length);
876 	}
877 
878 	if (argp->mech_type.GSS_OID_len == 0)
879 		mech_type = GSS_C_NULL_OID;
880 	else {
881 		mech_type->length = (OM_uint32)argp->mech_type.GSS_OID_len;
882 		mech_type->elements = (void *)argp->mech_type.GSS_OID_val;
883 	}
884 
885 	if (gss_import_name(&minor_status, &external_name, name_type,
886 			    &internal_name) != GSS_S_COMPLETE) {
887 
888 		if (name_type != GSS_C_NULL_OID)
889 			free(name_type->elements);
890 		res->status = (OM_uint32)GSS_S_FAILURE;
891 		res->minor_status = minor_status;
892 
893 		return (TRUE);
894 	}
895 /*
896  * copy the XDR structured arguments into their corresponding local GSSAPI
897  * variables.
898  */
899 
900 	if (argp->input_chan_bindings.present == YES) {
901 		input_chan_bindings_ptr = &input_chan_bindings;
902 		input_chan_bindings.initiator_addrtype =
903 			(OM_uint32)argp->input_chan_bindings.
904 			initiator_addrtype;
905 		input_chan_bindings.initiator_address.length =
906 			(uint_t)argp->input_chan_bindings.initiator_address.
907 			GSS_BUFFER_T_len;
908 		input_chan_bindings.initiator_address.value =
909 			(void *)argp->input_chan_bindings.initiator_address.
910 			GSS_BUFFER_T_val;
911 		input_chan_bindings.acceptor_addrtype =
912 			(OM_uint32)argp->input_chan_bindings.acceptor_addrtype;
913 		input_chan_bindings.acceptor_address.length =
914 			(uint_t)argp->input_chan_bindings.acceptor_address.
915 			GSS_BUFFER_T_len;
916 		input_chan_bindings.acceptor_address.value =
917 			(void *)argp->input_chan_bindings.acceptor_address.
918 			GSS_BUFFER_T_val;
919 		input_chan_bindings.application_data.length =
920 			(uint_t)argp->input_chan_bindings.application_data.
921 			GSS_BUFFER_T_len;
922 		input_chan_bindings.application_data.value =
923 			(void *)argp->input_chan_bindings.application_data.
924 			GSS_BUFFER_T_val;
925 	} else {
926 		input_chan_bindings_ptr = GSS_C_NO_CHANNEL_BINDINGS;
927 		input_chan_bindings.initiator_addrtype = 0;
928 		input_chan_bindings.initiator_address.length = 0;
929 		input_chan_bindings.initiator_address.value = 0;
930 		input_chan_bindings.acceptor_addrtype = 0;
931 		input_chan_bindings.acceptor_address.length = 0;
932 		input_chan_bindings.acceptor_address.value = 0;
933 		input_chan_bindings.application_data.length = 0;
934 		input_chan_bindings.application_data.value = 0;
935 	}
936 
937 	if (argp->input_token.GSS_BUFFER_T_len == 0) {
938 		input_token_ptr = GSS_C_NO_BUFFER;
939 	} else {
940 		input_token_ptr = &input_token;
941 		input_token.length = (size_t)
942 				argp->input_token.GSS_BUFFER_T_len;
943 		input_token.value = (void *)argp->input_token.GSS_BUFFER_T_val;
944 	}
945 
946 /* call the gssapi routine */
947 
948 	res->status = (OM_uint32)gss_init_sec_context(&res->minor_status,
949 			(gss_cred_id_t)argp->claimant_cred_handle.
950 						GSS_CRED_ID_T_val,
951 					&context_handle,
952 					internal_name,
953 					mech_type,
954 					argp->req_flags,
955 					argp->time_req,
956 					input_chan_bindings_ptr,
957 					input_token_ptr,
958 					&actual_mech_type,
959 					&output_token,
960 					&res->ret_flags,
961 					&res->time_rec);
962 
963 	/*
964 	 * convert the output args from the parameter given in the call to the
965 	 * variable in the XDR result
966 	 */
967 
968 	if (res->status == (OM_uint32)GSS_S_COMPLETE ||
969 		res->status == (OM_uint32)GSS_S_CONTINUE_NEEDED) {
970 
971 		if (slot == NULL || slot->ctx != context_handle) {
972 			/*
973 			 * Note that gssd_alloc_slot() will delete ctx's as long
974 			 * as we don't call gssd_rel_slot().
975 			 */
976 			slot = gssd_alloc_slot(context_handle);
977 		}
978 
979 		res->gssd_context_verifier = slot->verf;
980 
981 		res->context_handle.GSS_CTX_ID_T_len = sizeof (gss_ctx_id_t);
982 		res->context_handle.GSS_CTX_ID_T_val =
983 			(void *)malloc(sizeof (gss_ctx_id_t));
984 		if (!res->context_handle.GSS_CTX_ID_T_val) {
985 			free(name_type->elements);
986 			return (GSS_S_FAILURE);
987 		}
988 
989 		memcpy(res->context_handle.GSS_CTX_ID_T_val, &slot->rpcctx,
990 			sizeof (gss_ctx_id_t));
991 
992 		res->output_token.GSS_BUFFER_T_len =
993 			(uint_t)output_token.length;
994 		res->output_token.GSS_BUFFER_T_val =
995 			(char *)output_token.value;
996 
997 		/*
998 		 * the actual mech type parameter
999 		 * is ready only upon GSS_S_COMPLETE
1000 		 */
1001 		if (res->status == GSS_S_COMPLETE) {
1002 			res->actual_mech_type.GSS_OID_len =
1003 				(uint_t)actual_mech_type->length;
1004 			res->actual_mech_type.GSS_OID_val =
1005 				(void *)malloc(actual_mech_type->length);
1006 			if (!res->actual_mech_type.GSS_OID_val) {
1007 				free(name_type->elements);
1008 				free(res->context_handle.GSS_CTX_ID_T_val);
1009 				return (GSS_S_FAILURE);
1010 			}
1011 			memcpy(res->actual_mech_type.GSS_OID_val,
1012 				(char *)actual_mech_type->elements,
1013 				actual_mech_type->length);
1014 		} else
1015 			res->actual_mech_type.GSS_OID_len = 0;
1016 	} else {
1017 		if (context_handle != GSS_C_NO_CONTEXT) {
1018 			(void) gss_delete_sec_context(&minor_status,
1019 				&context_handle, NULL);
1020 		}
1021 		res->context_handle.GSS_CTX_ID_T_len = 0;
1022 		res->actual_mech_type.GSS_OID_len = 0;
1023 		res->output_token.GSS_BUFFER_T_len = 0;
1024 	}
1025 
1026 	/*
1027 	 * now release the space allocated by the underlying gssapi mechanism
1028 	 * library for internal_name and for the name_type.
1029 	 */
1030 
1031 	gss_release_name(&minor_status, &internal_name);
1032 	if (name_type != GSS_C_NULL_OID)
1033 		free(name_type->elements);
1034 
1035 
1036 	/* return to caller */
1037 	return (TRUE);
1038 }
1039 
1040 bool_t
1041 gss_accept_sec_context_1_svc(argp, res, rqstp)
1042 gss_accept_sec_context_arg *argp;
1043 gss_accept_sec_context_res *res;
1044 struct svc_req *rqstp;
1045 {
1046 	uid_t uid;
1047 	OM_uint32 minor_status;
1048 	gss_ctx_id_t context_handle = NULL;
1049 	gss_cred_id_t verifier_cred_handle;
1050 	gss_buffer_desc external_name;
1051 	gss_name_t internal_name = NULL;
1052 
1053 	gss_buffer_desc input_token_buffer;
1054 	gss_buffer_t input_token_buffer_ptr;
1055 	struct gss_channel_bindings_struct
1056 			input_chan_bindings;
1057 	gss_channel_bindings_t input_chan_bindings_ptr;
1058 	gss_OID mech_type;
1059 	gss_buffer_desc output_token;
1060 	gss_cred_id_t delegated_cred_handle;
1061 	bool_t context_verf_ok;
1062 	struct gssd_ctx_slot *slot = NULL;
1063 
1064 	memset(res, 0, sizeof (*res));
1065 
1066 	if (gssd_debug)
1067 		fprintf(stderr, gettext("gss_accept_sec_context\n"));
1068 
1069 	/*
1070 	 * if the request isn't from root, null out the result pointer
1071 	 * entries, so the next time through xdr_free won't try to
1072 	 * free unmalloc'd memory and then return NULL
1073 	 */
1074 
1075 	if (checkfrom(rqstp, &uid) == 0) {
1076 		res->context_handle.GSS_CTX_ID_T_val = NULL;
1077 		res->src_name.GSS_BUFFER_T_val = NULL;
1078 		res->mech_type.GSS_OID_val = NULL;
1079 		res->output_token.GSS_BUFFER_T_val = NULL;
1080 		res->delegated_cred_handle.GSS_CRED_ID_T_val = NULL;
1081 		return (FALSE);
1082 	}
1083 
1084 	/* set the uid sent as the RPC argument */
1085 
1086 	uid = argp->uid;
1087 	set_gssd_uid(uid);
1088 
1089 	/*
1090 	 * copy the supplied context handle into the local context handle, so
1091 	 * it can be supplied to the gss_accept_sec_context call
1092 	 */
1093 
1094 	gssd_convert_context_handle(&argp->context_handle, &context_handle,
1095 		argp->gssd_context_verifier, &context_verf_ok, &slot);
1096 
1097 	if (context_handle != GSS_C_NO_CONTEXT)
1098 		/* verify the context_handle */
1099 		if (!context_verf_ok) {
1100 			res->context_handle.GSS_CTX_ID_T_val = NULL;
1101 			res->src_name.GSS_BUFFER_T_val = NULL;
1102 			res->mech_type.GSS_OID_val = NULL;
1103 			res->output_token.GSS_BUFFER_T_val = NULL;
1104 			res->delegated_cred_handle.GSS_CRED_ID_T_val = NULL;
1105 			res->src_name.GSS_BUFFER_T_len = 0;
1106 			res->context_handle.GSS_CTX_ID_T_len = 0;
1107 			res->delegated_cred_handle.GSS_CRED_ID_T_len = 0;
1108 			res->output_token.GSS_BUFFER_T_len = 0;
1109 			res->mech_type.GSS_OID_len = 0;
1110 			res->status = (OM_uint32)GSS_S_NO_CONTEXT;
1111 			res->minor_status = 0;
1112 			return (TRUE);
1113 		}
1114 
1115 	/*
1116 	 * copy the XDR structured arguments into their corresponding local
1117 	 * GSSAPI variable equivalents.
1118 	 */
1119 
1120 
1121 	verifier_cred_handle =
1122 		(argp->verifier_cred_handle.GSS_CRED_ID_T_len == 0 ?
1123 			GSS_C_NO_CREDENTIAL :
1124 			/*LINTED*/
1125 			*((gss_cred_id_t *)argp->verifier_cred_handle.
1126 				GSS_CRED_ID_T_val));
1127 
1128 	if (verifier_cred_handle != GSS_C_NO_CREDENTIAL)
1129 	/* verify the verifier_cred_handle */
1130 		if (argp->gssd_cred_verifier != gssd_time_verf) {
1131 			res->context_handle.GSS_CTX_ID_T_val = NULL;
1132 			res->src_name.GSS_BUFFER_T_val = NULL;
1133 			res->mech_type.GSS_OID_val = NULL;
1134 			res->output_token.GSS_BUFFER_T_val = NULL;
1135 			res->delegated_cred_handle.GSS_CRED_ID_T_val = NULL;
1136 			res->src_name.GSS_BUFFER_T_len = 0;
1137 			res->context_handle.GSS_CTX_ID_T_len = 0;
1138 			res->delegated_cred_handle.GSS_CRED_ID_T_len = 0;
1139 			res->output_token.GSS_BUFFER_T_len = 0;
1140 			res->mech_type.GSS_OID_len = 0;
1141 			res->status = (OM_uint32)GSS_S_DEFECTIVE_CREDENTIAL;
1142 			res->minor_status = 0;
1143 			return (TRUE);
1144 		}
1145 
1146 	input_token_buffer_ptr = &input_token_buffer;
1147 	input_token_buffer.length = (size_t)argp->input_token_buffer.
1148 		GSS_BUFFER_T_len;
1149 	input_token_buffer.value = (void *)argp->input_token_buffer.
1150 		GSS_BUFFER_T_val;
1151 
1152 	if (argp->input_chan_bindings.present == YES) {
1153 		input_chan_bindings_ptr = &input_chan_bindings;
1154 		input_chan_bindings.initiator_addrtype =
1155 			(OM_uint32)argp->input_chan_bindings.
1156 					initiator_addrtype;
1157 		input_chan_bindings.initiator_address.length =
1158 			(uint_t)argp->input_chan_bindings.initiator_address.
1159 					GSS_BUFFER_T_len;
1160 		input_chan_bindings.initiator_address.value =
1161 			(void *)argp->input_chan_bindings.initiator_address.
1162 					GSS_BUFFER_T_val;
1163 		input_chan_bindings.acceptor_addrtype =
1164 			(OM_uint32)argp->input_chan_bindings.
1165 					acceptor_addrtype;
1166 		input_chan_bindings.acceptor_address.length =
1167 			(uint_t)argp->input_chan_bindings.acceptor_address.
1168 					GSS_BUFFER_T_len;
1169 		input_chan_bindings.acceptor_address.value =
1170 			(void *)argp->input_chan_bindings.acceptor_address.
1171 					GSS_BUFFER_T_val;
1172 		input_chan_bindings.application_data.length =
1173 			(uint_t)argp->input_chan_bindings.application_data.
1174 					GSS_BUFFER_T_len;
1175 		input_chan_bindings.application_data.value =
1176 			(void *)argp->input_chan_bindings.application_data.
1177 					GSS_BUFFER_T_val;
1178 	} else {
1179 		input_chan_bindings_ptr = GSS_C_NO_CHANNEL_BINDINGS;
1180 		input_chan_bindings.initiator_addrtype = 0;
1181 		input_chan_bindings.initiator_address.length = 0;
1182 		input_chan_bindings.initiator_address.value = 0;
1183 		input_chan_bindings.acceptor_addrtype = 0;
1184 		input_chan_bindings.acceptor_address.length = 0;
1185 		input_chan_bindings.acceptor_address.value = 0;
1186 		input_chan_bindings.application_data.length = 0;
1187 		input_chan_bindings.application_data.value = 0;
1188 	}
1189 
1190 
1191 	/* call the gssapi routine */
1192 
1193 	res->status = (OM_uint32)gss_accept_sec_context(&res->minor_status,
1194 						&context_handle,
1195 						verifier_cred_handle,
1196 						input_token_buffer_ptr,
1197 						input_chan_bindings_ptr,
1198 						&internal_name,
1199 						&mech_type,
1200 						&output_token,
1201 						&res->ret_flags,
1202 						&res->time_rec,
1203 						&delegated_cred_handle);
1204 
1205 	/* convert the src name from internal to external format */
1206 
1207 	if (res->status == (OM_uint32)GSS_S_COMPLETE ||
1208 		res->status == (OM_uint32)GSS_S_CONTINUE_NEEDED) {
1209 
1210 		/*
1211 		 * upon GSS_S_CONTINUE_NEEDED only the following
1212 		 * parameters are ready: minor, ctxt, and output token
1213 		 */
1214 		res->context_handle.GSS_CTX_ID_T_len = sizeof (gss_ctx_id_t);
1215 		res->context_handle.GSS_CTX_ID_T_val =
1216 			(void *)malloc(sizeof (gss_ctx_id_t));
1217 		if (!res->context_handle.GSS_CTX_ID_T_val) {
1218 			res->status = (OM_uint32)GSS_S_FAILURE;
1219 			res->minor_status = 0;
1220 			return (TRUE);
1221 		}
1222 
1223 		if (slot == NULL || slot->ctx != context_handle) {
1224 			/*
1225 			 * Note that gssd_alloc_slot() will delete ctx's as long
1226 			 * as we don't call gssd_rel_slot().
1227 			 */
1228 			slot = gssd_alloc_slot(context_handle);
1229 		}
1230 
1231 		memcpy(res->context_handle.GSS_CTX_ID_T_val, &slot->rpcctx,
1232 			sizeof (gss_ctx_id_t));
1233 		res->gssd_context_verifier = slot->verf;
1234 
1235 		res->output_token.GSS_BUFFER_T_len =
1236 				(uint_t)output_token.length;
1237 		res->output_token.GSS_BUFFER_T_val =
1238 				(char *)output_token.value;
1239 
1240 		if (res->status == GSS_S_COMPLETE) {
1241 			if (gss_export_name(&minor_status, internal_name,
1242 					&external_name)
1243 				!= GSS_S_COMPLETE) {
1244 
1245 				res->status = (OM_uint32)GSS_S_FAILURE;
1246 				res->minor_status = minor_status;
1247 				gss_release_name(&minor_status, &internal_name);
1248 				gss_delete_sec_context(&minor_status,
1249 						&context_handle, NULL);
1250 				free(res->context_handle.GSS_CTX_ID_T_val);
1251 				res->context_handle.GSS_CTX_ID_T_val = NULL;
1252 				res->context_handle.GSS_CTX_ID_T_len = 0;
1253 				gss_release_buffer(&minor_status,
1254 						&output_token);
1255 				res->output_token.GSS_BUFFER_T_len = 0;
1256 				res->output_token.GSS_BUFFER_T_val = NULL;
1257 				return (TRUE);
1258 			}
1259 			res->src_name.GSS_BUFFER_T_len =
1260 				(uint_t)external_name.length;
1261 			res->src_name.GSS_BUFFER_T_val =
1262 				(void *)external_name.value;
1263 
1264 			res->delegated_cred_handle.GSS_CRED_ID_T_len =
1265 				sizeof (gss_cred_id_t);
1266 			res->delegated_cred_handle.GSS_CRED_ID_T_val =
1267 				(void *)malloc(sizeof (gss_cred_id_t));
1268 			if (!res->delegated_cred_handle.GSS_CRED_ID_T_val) {
1269 				free(res->context_handle.GSS_CTX_ID_T_val);
1270 				gss_release_name(&minor_status, &internal_name);
1271 				gss_delete_sec_context(&minor_status,
1272 						&context_handle, NULL);
1273 				gss_release_buffer(&minor_status,
1274 						&external_name);
1275 				res->status = (OM_uint32)GSS_S_FAILURE;
1276 				res->minor_status = 0;
1277 				return (TRUE);
1278 			}
1279 			memcpy(res->delegated_cred_handle.GSS_CRED_ID_T_val,
1280 				&delegated_cred_handle,
1281 				sizeof (gss_cred_id_t));
1282 
1283 			res->mech_type.GSS_OID_len = (uint_t)mech_type->length;
1284 			res->mech_type.GSS_OID_val =
1285 				(void *)malloc(mech_type->length);
1286 			if (!res->mech_type.GSS_OID_val) {
1287 			    free(res->context_handle.GSS_CTX_ID_T_val);
1288 			    free(res->delegated_cred_handle.GSS_CRED_ID_T_val);
1289 			    gss_release_name(&minor_status, &internal_name);
1290 			    gss_delete_sec_context(&minor_status,
1291 						&context_handle, NULL);
1292 			    gss_release_buffer(&minor_status, &external_name);
1293 			    res->status = (OM_uint32)GSS_S_FAILURE;
1294 			    res->minor_status = 0;
1295 			    return (TRUE);
1296 			}
1297 			memcpy(res->mech_type.GSS_OID_val, mech_type->elements,
1298 				mech_type->length);
1299 
1300 			/* release the space allocated for internal_name */
1301 			gss_release_name(&minor_status, &internal_name);
1302 
1303 		} else {    /* GSS_S_CONTINUE_NEEDED */
1304 			res->src_name.GSS_BUFFER_T_len = 0;
1305 			res->delegated_cred_handle.GSS_CRED_ID_T_len = 0;
1306 			res->mech_type.GSS_OID_len = 0;
1307 		}
1308 	} else {
1309 		if (context_handle != GSS_C_NO_CONTEXT) {
1310 			(void) gss_delete_sec_context(&minor_status,
1311 				&context_handle, NULL);
1312 		}
1313 		res->src_name.GSS_BUFFER_T_len = 0;
1314 		res->context_handle.GSS_CTX_ID_T_len = 0;
1315                 res->delegated_cred_handle.GSS_CRED_ID_T_len = 0;
1316                 res->output_token.GSS_BUFFER_T_len =
1317 			(uint_t)output_token.length;
1318                 res->output_token.GSS_BUFFER_T_val =
1319 			(char *)output_token.value;
1320 
1321                 res->mech_type.GSS_OID_len = 0;
1322 	}
1323 
1324 /* return to caller */
1325 
1326 	return (TRUE);
1327 }
1328 
1329 bool_t
1330 gss_process_context_token_1_svc(argp, res, rqstp)
1331 gss_process_context_token_arg *argp;
1332 gss_process_context_token_res *res;
1333 struct svc_req *rqstp;
1334 {
1335 
1336 	uid_t uid;
1337 	gss_buffer_desc token_buffer;
1338 	gss_ctx_id_t context_handle;
1339 	bool_t context_verf_ok;
1340 
1341 	memset(res, 0, sizeof (*res));
1342 
1343 	if (gssd_debug)
1344 		fprintf(stderr, gettext("gss_process_context_token\n"));
1345 
1346 	if (checkfrom(rqstp, &uid) == 0)
1347 		return (FALSE);
1348 
1349 	gssd_convert_context_handle(&argp->context_handle, &context_handle,
1350 		argp->gssd_context_verifier, &context_verf_ok, NULL);
1351 
1352 	/* verify the context_handle */
1353 
1354 	if (!context_verf_ok) {
1355 		res->status = (OM_uint32) GSS_S_NO_CONTEXT;
1356 		res->minor_status = 0;
1357 		return (TRUE);
1358 	}
1359 
1360 	/* set the uid sent as the RPC argument */
1361 
1362 	uid = argp->uid;
1363 	set_gssd_uid(uid);
1364 
1365 	/*
1366 	 * copy the XDR structured arguments into their corresponding local
1367 	 * GSSAPI variable equivalents.
1368 	 */
1369 
1370 	token_buffer.length = (size_t)argp->token_buffer.GSS_BUFFER_T_len;
1371 	token_buffer.value = (void *)argp->token_buffer.GSS_BUFFER_T_val;
1372 
1373 
1374 	/* call the gssapi routine */
1375 
1376 	res->status = (OM_uint32)gss_process_context_token(&res->minor_status,
1377 				context_handle,
1378 				&token_buffer);
1379 
1380 
1381 	/* return to caller */
1382 
1383 	return (TRUE);
1384 }
1385 
1386 bool_t
1387 gss_delete_sec_context_1_svc(argp, res, rqstp)
1388 gss_delete_sec_context_arg *argp;
1389 gss_delete_sec_context_res *res;
1390 struct svc_req *rqstp;
1391 {
1392 	uid_t uid;
1393 	gss_ctx_id_t  context_handle;
1394 	gss_buffer_desc output_token;
1395 	bool_t context_verf_ok;
1396 	struct gssd_ctx_slot *slot = NULL;
1397 
1398 	memset(res, 0, sizeof (*res));
1399 
1400 	if (gssd_debug)
1401 		fprintf(stderr, gettext("gss_delete_sec_context\n"));
1402 
1403 
1404 	/*
1405 	 * copy the supplied context handle into the local context handle, so it
1406 	 * can be supplied to the gss_delete_sec_context call
1407 	 */
1408 	gssd_convert_context_handle(&argp->context_handle, &context_handle,
1409 		argp->gssd_context_verifier, &context_verf_ok, &slot);
1410 
1411 	/* verify the context_handle */
1412 	if (!context_verf_ok) {
1413 		res->context_handle.GSS_CTX_ID_T_val = NULL;
1414 		res->context_handle.GSS_CTX_ID_T_len = 0;
1415 		res->output_token.GSS_BUFFER_T_val = NULL;
1416 		res->output_token.GSS_BUFFER_T_len = 0;
1417 		res->status = (OM_uint32)GSS_S_NO_CONTEXT;
1418 		res->minor_status = 0;
1419 		return (TRUE);
1420 	}
1421 
1422 	/*
1423 	 * if the request isn't from root, null out the result pointer
1424 	 * entries, so the next time through xdr_free won't try to
1425 	 * free unmalloc'd memory and then return NULL
1426 	 */
1427 
1428 	if (checkfrom(rqstp, &uid) == 0) {
1429 		res->context_handle.GSS_CTX_ID_T_val = NULL;
1430 		res->output_token.GSS_BUFFER_T_val = NULL;
1431 		return (FALSE);
1432 	}
1433 
1434 	/* call the gssapi routine */
1435 
1436 	res->status = (OM_uint32)gss_delete_sec_context(&res->minor_status,
1437 						&context_handle,
1438 						&output_token);
1439 
1440 	/*
1441 	 * convert the output args from the parameter given in the call to the
1442 	 * variable in the XDR result. If the delete succeeded, return a zero
1443 	 * context handle.
1444 	 */
1445 
1446 	if (res->status == GSS_S_COMPLETE) {
1447 		if (context_handle != GSS_C_NO_CONTEXT)
1448 			return (GSS_S_FAILURE);
1449 		res->context_handle.GSS_CTX_ID_T_len = 0;
1450 		res->context_handle.GSS_CTX_ID_T_val = NULL;
1451 		res->output_token.GSS_BUFFER_T_len =
1452 			(uint_t)output_token.length;
1453 		res->output_token.GSS_BUFFER_T_val =
1454 			(char *)output_token.value;
1455 
1456 		if (slot != NULL) {
1457 			/*
1458 			 * gss_delete_sec_context deletes the context if it
1459 			 * succeeds so clear slot->ctx to avoid a dangling
1460 			 * reference.
1461 			 */
1462 			slot->ctx = GSS_C_NO_CONTEXT;
1463 			gssd_rel_slot(slot);
1464 		}
1465 	} else {
1466 		res->context_handle.GSS_CTX_ID_T_len = sizeof (gss_ctx_id_t);
1467 		res->context_handle.GSS_CTX_ID_T_val =
1468 			(void *)malloc(sizeof (gss_ctx_id_t));
1469 		if (!res->context_handle.GSS_CTX_ID_T_val) {
1470 			return (GSS_S_FAILURE);
1471 		}
1472 
1473 		if (slot == NULL || slot->ctx != context_handle) {
1474 			/*
1475 			 * Note that gssd_alloc_slot() will delete ctx's as long
1476 			 * as we don't call gssd_rel_slot().
1477 			 */
1478 			slot = gssd_alloc_slot(context_handle);
1479 			/*
1480 			 * Note that no verifier is returned in the .x
1481 			 * protocol. So if the context changes, we won't
1482 			 * be able to release it now. So it will have to
1483 			 * be LRUed out.
1484 			 */
1485 		}
1486 
1487 		memcpy(res->context_handle.GSS_CTX_ID_T_val, &slot->rpcctx,
1488 			sizeof (gss_ctx_id_t));
1489 
1490 		res->output_token.GSS_BUFFER_T_len = 0;
1491 		res->output_token.GSS_BUFFER_T_val = NULL;
1492 	}
1493 
1494 	/* return to caller */
1495 
1496 
1497 	return (TRUE);
1498 }
1499 
1500 
1501 bool_t
1502 gss_export_sec_context_1_svc(argp, res, rqstp)
1503 	gss_export_sec_context_arg *argp;
1504 	gss_export_sec_context_res *res;
1505 	struct svc_req *rqstp;
1506 {
1507 
1508 	uid_t		uid;
1509 	gss_ctx_id_t	context_handle;
1510 	gss_buffer_desc	output_token;
1511 	bool_t		context_verf_ok;
1512 	struct gssd_ctx_slot *slot = NULL;
1513 
1514 	memset(res, 0, sizeof (*res));
1515 
1516 	if (gssd_debug)
1517 		fprintf(stderr, "gss_export_sec_context\n");
1518 
1519 	/*
1520 	 * if the request isn't from root, null out the result pointer
1521 	 * entries, so the next time through xdr_free won't try to
1522 	 * free unmalloc'd memory and then return NULL
1523 	 */
1524 
1525 	if (checkfrom(rqstp, &uid) == 0) {
1526 		res->context_handle.GSS_CTX_ID_T_val = NULL;
1527 		res->output_token.GSS_BUFFER_T_val = NULL;
1528 		return (FALSE);
1529 	}
1530 
1531 /*
1532  * copy the supplied context handle into the local context handle, so it
1533  * can be supplied to the gss_export_sec_context call
1534  */
1535 
1536 	gssd_convert_context_handle(&argp->context_handle, &context_handle,
1537 		argp->gssd_context_verifier, &context_verf_ok, &slot);
1538 
1539 	/* verify the context_handle */
1540 
1541 	if (!context_verf_ok) {
1542 		res->status = (OM_uint32)GSS_S_NO_CONTEXT;
1543 		/* the rest of "res" was cleared by a previous memset() */
1544 		return (TRUE);
1545 	}
1546 
1547 	/* call the gssapi routine */
1548 
1549 	res->status = (OM_uint32)gss_export_sec_context(&res->minor_status,
1550 					&context_handle,
1551 					&output_token);
1552 
1553 /*
1554  * convert the output args from the parameter given in the call to the
1555  * variable in the XDR result. If the delete succeeded, return a zero context
1556  * handle.
1557  */
1558 	if (res->status == GSS_S_COMPLETE) {
1559 		if (context_handle != GSS_C_NO_CONTEXT)
1560 			return (GSS_S_FAILURE);
1561 		res->context_handle.GSS_CTX_ID_T_len = 0;
1562 		res->context_handle.GSS_CTX_ID_T_val = NULL;
1563 		res->output_token.GSS_BUFFER_T_len =
1564 						(uint_t)output_token.length;
1565 		res->output_token.GSS_BUFFER_T_val =
1566 						(char *)output_token.value;
1567 
1568 		if (slot != NULL) {
1569 			/*
1570 			 * gss_export_sec_context deletes the context if it
1571 			 * succeeds so set slot->ctx to avoid a dangling
1572 			 * reference.
1573 			 */
1574 			slot->ctx = GSS_C_NO_CONTEXT;
1575 			gssd_rel_slot(slot);
1576 		}
1577 	} else {
1578 		res->context_handle.GSS_CTX_ID_T_len = sizeof (gss_ctx_id_t);
1579 		res->context_handle.GSS_CTX_ID_T_val =
1580 					(void *)malloc(sizeof (gss_ctx_id_t));
1581 
1582 		if (slot == NULL || slot->ctx != context_handle) {
1583 			/*
1584 			 * Note that gssd_alloc_slot() will delete ctx's as long
1585 			 * as we don't call gssd_rel_slot().
1586 			 */
1587 			slot = gssd_alloc_slot(context_handle);
1588 			/*
1589 			 * Note that no verifier is returned in the .x
1590 			 * protocol. So if the context changes, we won't
1591 			 * be able to release it now. So it will have to
1592 			 * be LRUed out.
1593 			 */
1594 		}
1595 
1596 		memcpy(res->context_handle.GSS_CTX_ID_T_val, &slot->rpcctx,
1597 			sizeof (gss_ctx_id_t));
1598 		res->output_token.GSS_BUFFER_T_len = 0;
1599 		res->output_token.GSS_BUFFER_T_val = NULL;
1600 	}
1601 
1602 
1603 	/* return to caller */
1604 
1605 	return (TRUE);
1606 }
1607 
1608 /*
1609  * This routine doesn't appear to ever be called.
1610  */
1611 bool_t
1612 gss_import_sec_context_1_svc(argp, res, rqstp)
1613 	gss_import_sec_context_arg *argp;
1614 	gss_import_sec_context_res *res;
1615 	struct svc_req *rqstp;
1616 {
1617 
1618 	uid_t		uid;
1619 	gss_ctx_id_t	context_handle;
1620 	gss_buffer_desc	input_token;
1621 	gss_buffer_t input_token_ptr;
1622 
1623 	memset(res, 0, sizeof (*res));
1624 
1625 	if (gssd_debug)
1626 		fprintf(stderr, "gss_export_sec_context\n");
1627 
1628 	/*
1629 	 * if the request isn't from root, null out the result pointer
1630 	 * entries, so the next time through xdr_free won't try to
1631 	 * free unmalloc'd memory and then return NULL
1632 	 */
1633 
1634 	if (checkfrom(rqstp, &uid) == 0) {
1635 		res->context_handle.GSS_CTX_ID_T_val = NULL;
1636 		return (FALSE);
1637 	}
1638 
1639 
1640 	if (argp->input_token.GSS_BUFFER_T_len == 0) {
1641 		input_token_ptr = GSS_C_NO_BUFFER;
1642 	} else {
1643 		input_token_ptr = &input_token;
1644 		input_token.length = (size_t)
1645 				argp->input_token.GSS_BUFFER_T_len;
1646 		input_token.value = (void *) argp->input_token.GSS_BUFFER_T_val;
1647 	}
1648 
1649 
1650 /* call the gssapi routine */
1651 
1652 	res->status = (OM_uint32) gss_import_sec_context(&res->minor_status,
1653 					input_token_ptr,
1654 					&context_handle);
1655 
1656 /*
1657  * convert the output args from the parameter given in the call to the
1658  * variable in the XDR result. If the delete succeeded, return a zero context
1659  * handle.
1660  */
1661 	if (res->status == GSS_S_COMPLETE) {
1662 		res->context_handle.GSS_CTX_ID_T_len = sizeof (gss_ctx_id_t);
1663 		res->context_handle.GSS_CTX_ID_T_val =
1664 					(void *) malloc(sizeof (gss_ctx_id_t));
1665 		memcpy(res->context_handle.GSS_CTX_ID_T_val, &context_handle,
1666 			sizeof (gss_ctx_id_t));
1667 	} else {
1668 		res->context_handle.GSS_CTX_ID_T_len = 0;
1669 		res->context_handle.GSS_CTX_ID_T_val = NULL;
1670 	}
1671 
1672 
1673 	/* return to caller */
1674 
1675 	return (TRUE);
1676 }
1677 
1678 bool_t
1679 gss_context_time_1_svc(argp, res, rqstp)
1680 gss_context_time_arg *argp;
1681 gss_context_time_res *res;
1682 struct svc_req *rqstp;
1683 {
1684 	uid_t uid;
1685 
1686 	memset(res, 0, sizeof (*res));
1687 
1688 	if (gssd_debug)
1689 		fprintf(stderr, gettext("gss_context_time\n"));
1690 
1691 	/*
1692 	 * if the request isn't from root, null out the result pointer
1693 	 * entries, so the next time through xdr_free won't try to
1694 	 * free unmalloc'd memory and then return NULL
1695 	 */
1696 
1697 	if (checkfrom(rqstp, &uid) == 0)
1698 		return (FALSE);
1699 
1700 	/* set the uid sent as the RPC argument */
1701 
1702 	uid = argp->uid;
1703 	set_gssd_uid(uid);
1704 
1705 	/* Semantics go here */
1706 
1707 	return (TRUE);
1708 }
1709 
1710 bool_t
1711 gss_sign_1_svc(argp, res, rqstp)
1712 gss_sign_arg *argp;
1713 gss_sign_res *res;
1714 struct svc_req *rqstp;
1715 {
1716 
1717 	uid_t uid;
1718 
1719 	gss_buffer_desc message_buffer;
1720 	gss_buffer_desc msg_token;
1721 	gss_ctx_id_t	context_handle;
1722 	bool_t context_verf_ok;
1723 
1724 	memset(res, 0, sizeof (*res));
1725 
1726 	if (gssd_debug)
1727 		fprintf(stderr, gettext("gss_sign\n"));
1728 
1729 	gssd_convert_context_handle(&argp->context_handle, &context_handle,
1730 		argp->gssd_context_verifier, &context_verf_ok, NULL);
1731 
1732 	/* verify the context_handle */
1733 	if (!context_verf_ok) {
1734 		res->msg_token.GSS_BUFFER_T_val = NULL;
1735 		res->msg_token.GSS_BUFFER_T_len = 0;
1736 		res->status = (OM_uint32) GSS_S_NO_CONTEXT;
1737 		res->minor_status = 0;
1738 		return (TRUE);
1739 	}
1740 
1741 
1742 	/*
1743 	 * if the request isn't from root, null out the result pointer
1744 	 * entries, so the next time through xdr_free won't try to
1745 	 * free unmalloc'd memory and then return NULL
1746 	 */
1747 
1748 	if (checkfrom(rqstp, &uid) == 0) {
1749 		res->msg_token.GSS_BUFFER_T_val = NULL;
1750 		return (FALSE);
1751 	}
1752 
1753 	/*
1754 	 * copy the XDR structured arguments into their corresponding local
1755 	 * GSSAPI variable equivalents.
1756 	 */
1757 
1758 	message_buffer.length = (size_t)argp->message_buffer.GSS_BUFFER_T_len;
1759 	message_buffer.value = (void *)argp->message_buffer.GSS_BUFFER_T_val;
1760 
1761 	/* call the gssapi routine */
1762 
1763 	res->status = (OM_uint32)gss_sign(&res->minor_status,
1764 					context_handle,
1765 					argp->qop_req,
1766 					(gss_buffer_t)&message_buffer,
1767 					(gss_buffer_t)&msg_token);
1768 	/*
1769 	 * convert the output args from the parameter given in the call to
1770 	 * the variable in the XDR result
1771 	 */
1772 
1773 	if (res->status == GSS_S_COMPLETE) {
1774 		res->msg_token.GSS_BUFFER_T_len = (uint_t)msg_token.length;
1775 		res->msg_token.GSS_BUFFER_T_val = (char *)msg_token.value;
1776 	}
1777 
1778 	/* return to caller */
1779 
1780 	return (TRUE);
1781 }
1782 
1783 bool_t
1784 gss_verify_1_svc(argp, res, rqstp)
1785 gss_verify_arg *argp;
1786 gss_verify_res *res;
1787 struct svc_req *rqstp;
1788 {
1789 
1790 	uid_t uid;
1791 
1792 	gss_buffer_desc message_buffer;
1793 	gss_buffer_desc token_buffer;
1794 	gss_ctx_id_t context_handle;
1795 	bool_t context_verf_ok;
1796 
1797 	memset(res, 0, sizeof (*res));
1798 
1799 	if (gssd_debug)
1800 		fprintf(stderr, gettext("gss_verify\n"));
1801 
1802 	gssd_convert_context_handle(&argp->context_handle, &context_handle,
1803 		argp->gssd_context_verifier, &context_verf_ok, NULL);
1804 
1805 	/* verify the context_handle */
1806 	if (!context_verf_ok) {
1807 		res->status = (OM_uint32) GSS_S_NO_CONTEXT;
1808 		res->minor_status = 0;
1809 		return (TRUE);
1810 	}
1811 
1812 	/*
1813 	 * if the request isn't from root, null out the result pointer
1814 	 * entries, so the next time through xdr_free won't try to
1815 	 * free unmalloc'd memory and then return NULL
1816 	 */
1817 
1818 	if (checkfrom(rqstp, &uid) == 0)
1819 		return (FALSE);
1820 
1821 	/*
1822 	 * copy the XDR structured arguments into their corresponding local
1823 	 * GSSAPI variable equivalents.
1824 	 */
1825 
1826 	message_buffer.length = (size_t)argp->message_buffer.GSS_BUFFER_T_len;
1827 	message_buffer.value = (void *)argp->message_buffer.GSS_BUFFER_T_val;
1828 
1829 	token_buffer.length = (size_t)argp->token_buffer.GSS_BUFFER_T_len;
1830 	token_buffer.value = (void *)argp->token_buffer.GSS_BUFFER_T_val;
1831 
1832 	/* call the gssapi routine */
1833 
1834 	res->status = (OM_uint32)gss_verify(&res->minor_status,
1835 				context_handle,
1836 				&message_buffer,
1837 				&token_buffer,
1838 				&res->qop_state);
1839 
1840 	/* return to caller */
1841 
1842 	return (TRUE);
1843 }
1844 
1845 /* EXPORT DELETE START */
1846 
1847 bool_t
1848 gss_seal_1_svc(argp, res, rqstp)
1849 gss_seal_arg *argp;
1850 gss_seal_res *res;
1851 struct svc_req *rqstp;
1852 {
1853 	uid_t uid;
1854 
1855 	gss_buffer_desc input_message_buffer;
1856 	gss_buffer_desc output_message_buffer;
1857 	gss_ctx_id_t context_handle;
1858 	bool_t context_verf_ok;
1859 
1860 	memset(res, 0, sizeof (*res));
1861 
1862 	if (gssd_debug)
1863 		fprintf(stderr, gettext("gss_seal\n"));
1864 
1865 	gssd_convert_context_handle(&argp->context_handle, &context_handle,
1866 		argp->gssd_context_verifier, &context_verf_ok, NULL);
1867 
1868 	/* verify the context_handle */
1869 
1870 	if (!context_verf_ok) {
1871 		res->output_message_buffer.GSS_BUFFER_T_val = NULL;
1872 		res->output_message_buffer.GSS_BUFFER_T_len = 0;
1873 		res->status = (OM_uint32) GSS_S_NO_CONTEXT;
1874 		res->minor_status = 0;
1875 		return (TRUE);
1876 	}
1877 
1878 	/*
1879 	 * if the request isn't from root, null out the result pointer
1880 	 * entries, so the next time through xdr_free won't try to
1881 	 * free unmalloc'd memory and then return NULL
1882 	 */
1883 
1884 	if (checkfrom(rqstp, &uid) == 0) {
1885 		res->output_message_buffer.GSS_BUFFER_T_val = NULL;
1886 		return (FALSE);
1887 
1888 	}
1889 
1890 
1891 	/*
1892 	 * copy the XDR structured arguments into their corresponding local
1893 	 * GSSAPI variable equivalents.
1894 	 */
1895 
1896 	input_message_buffer.length = (size_t)argp->input_message_buffer.
1897 					GSS_BUFFER_T_len;
1898 	input_message_buffer.value = (void *)argp->input_message_buffer.
1899 					GSS_BUFFER_T_val;
1900 
1901 
1902 	/* call the gssapi routine */
1903 
1904 	res->status = (OM_uint32)gss_seal(&res->minor_status,
1905 				context_handle,
1906 				argp->conf_req_flag,
1907 				argp->qop_req,
1908 				&input_message_buffer,
1909 				&res->conf_state,
1910 				&output_message_buffer);
1911 	/*
1912 	 * convert the output args from the parameter given in the call to the
1913 	 * variable in the XDR result
1914 	 */
1915 
1916 	if (res->status == GSS_S_COMPLETE) {
1917 		res->output_message_buffer.GSS_BUFFER_T_len =
1918 				(uint_t)output_message_buffer.length;
1919 		res->output_message_buffer.GSS_BUFFER_T_val =
1920 				(char *)output_message_buffer.value;
1921 	}
1922 
1923 /* return to caller */
1924 
1925 	return (TRUE);
1926 }
1927 
1928 bool_t
1929 gss_unseal_1_svc(argp, res, rqstp)
1930 gss_unseal_arg *argp;
1931 gss_unseal_res *res;
1932 struct svc_req *rqstp;
1933 {
1934 
1935 	uid_t uid;
1936 
1937 	gss_buffer_desc input_message_buffer;
1938 	gss_buffer_desc output_message_buffer;
1939 	gss_ctx_id_t context_handle;
1940 	bool_t context_verf_ok;
1941 
1942 	memset(res, 0, sizeof (*res));
1943 
1944 	if (gssd_debug)
1945 		fprintf(stderr, gettext("gss_unseal\n"));
1946 
1947 	/* verify the context_handle */
1948 	gssd_convert_context_handle(&argp->context_handle, &context_handle,
1949 		argp->gssd_context_verifier, &context_verf_ok, NULL);
1950 
1951 	/* verify the context_handle */
1952 	if (!context_verf_ok) {
1953 		res->output_message_buffer.GSS_BUFFER_T_val = NULL;
1954 		res->output_message_buffer.GSS_BUFFER_T_len = 0;
1955 		res->status = (OM_uint32)GSS_S_NO_CONTEXT;
1956 		res->minor_status = 0;
1957 		return (TRUE);
1958 	}
1959 
1960 	/*
1961 	 * if the request isn't from root, null out the result pointer
1962 	 * entries, so the next time through xdr_free won't try to
1963 	 * free unmalloc'd memory and then return NULL
1964 	 */
1965 
1966 	if (checkfrom(rqstp, &uid) == 0) {
1967 		res->output_message_buffer.GSS_BUFFER_T_val = NULL;
1968 		return (FALSE);
1969 	}
1970 
1971 
1972 	/*
1973 	 * copy the XDR structured arguments into their corresponding local
1974 	 * GSSAPI variable equivalents.
1975 	 */
1976 
1977 	input_message_buffer.length = (size_t)argp->input_message_buffer.
1978 					GSS_BUFFER_T_len;
1979 	input_message_buffer.value = (void *)argp->input_message_buffer.
1980 					GSS_BUFFER_T_val;
1981 
1982 	/* call the gssapi routine */
1983 
1984 	res->status = (OM_uint32)gss_unseal(&res->minor_status,
1985 				context_handle,
1986 				&input_message_buffer,
1987 				&output_message_buffer,
1988 				&res->conf_state,
1989 				&res->qop_state);
1990 
1991 	/*
1992 	 * convert the output args from the parameter given in the call to the
1993 	 * variable in the XDR result
1994 	 */
1995 
1996 	if (res->status == GSS_S_COMPLETE) {
1997 		res->output_message_buffer.GSS_BUFFER_T_len =
1998 				(uint_t)output_message_buffer.length;
1999 		res->output_message_buffer.GSS_BUFFER_T_val =
2000 				(char *)output_message_buffer.value;
2001 	}
2002 
2003 
2004 	/* return to caller */
2005 
2006 	return (TRUE);
2007 }
2008 
2009 /* EXPORT DELETE END */
2010 
2011 bool_t
2012 gss_display_status_1_svc(argp, res, rqstp)
2013 gss_display_status_arg *argp;
2014 gss_display_status_res *res;
2015 struct svc_req *rqstp;
2016 {
2017 	uid_t uid;
2018 	gss_OID mech_type;
2019 	gss_OID_desc mech_type_desc;
2020 	gss_buffer_desc status_string;
2021 
2022 	memset(res, 0, sizeof (*res));
2023 
2024 	if (gssd_debug)
2025 		fprintf(stderr, gettext("gss_display_status\n"));
2026 
2027 	/*
2028 	 * if the request isn't from root, null out the result pointer
2029 	 * entries, so the next time through xdr_free won't try to
2030 	 * free unmalloc'd memory and then return NULL
2031 	 */
2032 
2033 	if (checkfrom(rqstp, &uid) == 0) {
2034 		res->status_string.GSS_BUFFER_T_val = NULL;
2035 		return (FALSE);
2036 	}
2037 
2038 	/* set the uid sent as the RPC argument */
2039 
2040 	uid = argp->uid;
2041 	set_gssd_uid(uid);
2042 
2043 	/*
2044 	 * copy the XDR structured arguments into their corresponding local
2045 	 * GSSAPI variables.
2046 	 */
2047 
2048 	if (argp->mech_type.GSS_OID_len == 0)
2049 		mech_type = GSS_C_NULL_OID;
2050 	else {
2051 		mech_type = &mech_type_desc;
2052 		mech_type_desc.length = (OM_uint32) argp->mech_type.GSS_OID_len;
2053 		mech_type_desc.elements = (void *) argp->mech_type.GSS_OID_val;
2054 	}
2055 
2056 
2057 	/* call the gssapi routine */
2058 
2059 	res->status = (OM_uint32) gss_display_status(&res->minor_status,
2060 					argp->status_value,
2061 					argp->status_type,
2062 					mech_type,
2063 					(OM_uint32 *)&res->message_context,
2064 					&status_string);
2065 
2066 	/*
2067 	 * convert the output args from the parameter given in the call to the
2068 	 * variable in the XDR result
2069 	 */
2070 
2071 	if (res->status == GSS_S_COMPLETE) {
2072 		res->status_string.GSS_BUFFER_T_len =
2073 			(uint_t)status_string.length;
2074 		res->status_string.GSS_BUFFER_T_val =
2075 			(char *)status_string.value;
2076 	}
2077 
2078 	return (TRUE);
2079 
2080 }
2081 
2082 /*ARGSUSED*/
2083 bool_t
2084 gss_indicate_mechs_1_svc(argp, res, rqstp)
2085 	void *argp;
2086 	gss_indicate_mechs_res *res;
2087 	struct svc_req *rqstp;
2088 {
2089 	gss_OID_set oid_set;
2090 	uid_t uid;
2091 
2092 	memset(res, 0, sizeof (*res));
2093 
2094 	if (gssd_debug)
2095 		fprintf(stderr, gettext("gss_indicate_mechs\n"));
2096 
2097 	res->mech_set.GSS_OID_SET_val = NULL;
2098 
2099 	/*
2100 	 * if the request isn't from root, null out the result pointer
2101 	 * entries, so the next time through xdr_free won't try to
2102 	 * free unmalloc'd memory and then return NULL
2103 	 */
2104 
2105 	if (checkfrom(rqstp, &uid) == 0) {
2106 		return (FALSE);
2107 	}
2108 
2109 	res->status = gss_indicate_mechs(&res->minor_status, &oid_set);
2110 
2111 	if (res->status == GSS_S_COMPLETE) {
2112 		int i, j;
2113 
2114 		res->mech_set.GSS_OID_SET_len = oid_set->count;
2115 		res->mech_set.GSS_OID_SET_val = (void *)
2116 				malloc(oid_set->count * sizeof (GSS_OID));
2117 		if (!res->mech_set.GSS_OID_SET_val) {
2118 			return (GSS_S_FAILURE);
2119 		}
2120 		for (i = 0; i < oid_set->count; i++) {
2121 			res->mech_set.GSS_OID_SET_val[i].GSS_OID_len =
2122 				oid_set->elements[i].length;
2123 			res->mech_set.GSS_OID_SET_val[i].GSS_OID_val =
2124 				(char *)malloc(oid_set->elements[i].length);
2125 			if (!res->mech_set.GSS_OID_SET_val[i].GSS_OID_val) {
2126 				for (j = 0; j < (i -1); j++) {
2127 				free
2128 				(res->mech_set.GSS_OID_SET_val[i].GSS_OID_val);
2129 				}
2130 				free(res->mech_set.GSS_OID_SET_val);
2131 				return (GSS_S_FAILURE);
2132 			}
2133 			memcpy(res->mech_set.GSS_OID_SET_val[i].GSS_OID_val,
2134 				oid_set->elements[i].elements,
2135 				oid_set->elements[i].length);
2136 		}
2137 	}
2138 
2139 	return (TRUE);
2140 }
2141 
2142 bool_t
2143 gss_inquire_cred_1_svc(argp, res, rqstp)
2144 gss_inquire_cred_arg *argp;
2145 gss_inquire_cred_res *res;
2146 struct svc_req *rqstp;
2147 {
2148 
2149 	uid_t uid;
2150 
2151 	OM_uint32 minor_status;
2152 	gss_cred_id_t cred_handle;
2153 	gss_buffer_desc external_name;
2154 	gss_OID name_type;
2155 	gss_name_t internal_name;
2156 	gss_OID_set mechanisms;
2157 	int i, j;
2158 
2159 	memset(res, 0, sizeof (*res));
2160 
2161 	if (gssd_debug)
2162 		fprintf(stderr, gettext("gss_inquire_cred\n"));
2163 
2164 	/* verify the verifier_cred_handle */
2165 
2166 	if (argp->gssd_cred_verifier != gssd_time_verf) {
2167 		res->name.GSS_BUFFER_T_val = NULL;
2168 		res->name_type.GSS_OID_val = NULL;
2169 		res->mechanisms.GSS_OID_SET_val = NULL;
2170 		res->status = (OM_uint32) GSS_S_DEFECTIVE_CREDENTIAL;
2171 		res->minor_status = 0;
2172 		return (TRUE);
2173 	}
2174 
2175 	/*
2176 	 * if the request isn't from root, null out the result pointer
2177 	 * entries, so the next time through xdr_free won't try to
2178 	 * free unmalloc'd memory and then return NULL
2179 	 */
2180 
2181 	if (checkfrom(rqstp, &uid) == 0) {
2182 		res->name.GSS_BUFFER_T_val = NULL;
2183 		res->name_type.GSS_OID_val = NULL;
2184 		res->mechanisms.GSS_OID_SET_val = NULL;
2185 		return (FALSE);
2186 	}
2187 
2188 	/* set the uid sent as the RPC argument */
2189 
2190 	uid = argp->uid;
2191 	set_gssd_uid(uid);
2192 
2193 	cred_handle = (argp->cred_handle.GSS_CRED_ID_T_len == 0 ?
2194 			GSS_C_NO_CREDENTIAL :
2195 			/*LINTED*/
2196 			*((gss_cred_id_t *)argp->cred_handle.
2197 				GSS_CRED_ID_T_val));
2198 
2199 	/* call the gssapi routine */
2200 
2201 	res->status = (OM_uint32)gss_inquire_cred(&res->minor_status,
2202 					cred_handle,
2203 					&internal_name,
2204 					&res->lifetime,
2205 					&res->cred_usage,
2206 					&mechanisms);
2207 
2208 	if (res->status != GSS_S_COMPLETE)
2209 		return (TRUE);
2210 
2211 	/* convert the returned name from internal to external format */
2212 
2213 	if (gss_display_name(&minor_status, internal_name,
2214 				&external_name, &name_type)
2215 			!= GSS_S_COMPLETE) {
2216 
2217 		res->status = (OM_uint32)GSS_S_FAILURE;
2218 		res->minor_status = minor_status;
2219 
2220 		gss_release_name(&minor_status, &internal_name);
2221 
2222 		if (mechanisms != GSS_C_NULL_OID_SET) {
2223 			for (i = 0; i < mechanisms->count; i++)
2224 				free(mechanisms->elements[i].elements);
2225 			free(mechanisms->elements);
2226 			free(mechanisms);
2227 		}
2228 
2229 		return (TRUE);
2230 	}
2231 
2232 	/*
2233 	 * convert the output args from the parameter given in the call to the
2234 	 * variable in the XDR result
2235 	 */
2236 
2237 
2238 	res->name.GSS_BUFFER_T_len = (uint_t)external_name.length;
2239 	res->name.GSS_BUFFER_T_val = (void *)external_name.value;
2240 
2241 	/*
2242 	 * we have to allocate storage for name_type here, since the value
2243 	 * returned from gss_display_name points to the underlying mechanism
2244 	 * static storage. If we didn't allocate storage, the next time
2245 	 * through this routine, the xdr_free() call at the beginning would
2246 	 * try to free up that static storage.
2247 	 */
2248 
2249 	res->name_type.GSS_OID_len = (uint_t)name_type->length;
2250 	res->name_type.GSS_OID_val = (void *)malloc(name_type->length);
2251 	if (!res->name_type.GSS_OID_val) {
2252 		return (GSS_S_FAILURE);
2253 	}
2254 	memcpy(res->name_type.GSS_OID_val, name_type->elements,
2255 		name_type->length);
2256 
2257 	if (mechanisms != GSS_C_NULL_OID_SET) {
2258 		res->mechanisms.GSS_OID_SET_len =
2259 			(uint_t)mechanisms->count;
2260 		res->mechanisms.GSS_OID_SET_val = (GSS_OID *)
2261 				malloc(sizeof (GSS_OID) * mechanisms->count);
2262 		if (!res->mechanisms.GSS_OID_SET_val) {
2263 			free(res->name_type.GSS_OID_val);
2264 			return (GSS_S_FAILURE);
2265 		}
2266 		for (i = 0; i < mechanisms->count; i++) {
2267 			res->mechanisms.GSS_OID_SET_val[i].GSS_OID_len =
2268 				(uint_t)mechanisms->elements[i].length;
2269 			res->mechanisms.GSS_OID_SET_val[i].GSS_OID_val =
2270 				(char *)malloc(mechanisms->elements[i].
2271 						length);
2272 			if (!res->mechanisms.GSS_OID_SET_val[i].GSS_OID_val) {
2273 				free(res->name_type.GSS_OID_val);
2274 				for (j = 0; j < i; j++) {
2275 				free(res->mechanisms.
2276 					GSS_OID_SET_val[i].GSS_OID_val);
2277 				}
2278 				free(res->mechanisms.GSS_OID_SET_val);
2279 				return (GSS_S_FAILURE);
2280 			}
2281 			memcpy(res->mechanisms.GSS_OID_SET_val[i].GSS_OID_val,
2282 				mechanisms->elements[i].elements,
2283 				mechanisms->elements[i].length);
2284 		}
2285 	} else
2286 		res->mechanisms.GSS_OID_SET_len = 0;
2287 
2288 	/* release the space allocated for internal_name and mechanisms */
2289 	gss_release_name(&minor_status, &internal_name);
2290 
2291 	if (mechanisms != GSS_C_NULL_OID_SET) {
2292 		for (i = 0; i < mechanisms->count; i++)
2293 			free(mechanisms->elements[i].elements);
2294 		free(mechanisms->elements);
2295 		free(mechanisms);
2296 	}
2297 
2298 	/* return to caller */
2299 	return (TRUE);
2300 }
2301 
2302 
2303 bool_t
2304 gss_inquire_cred_by_mech_1_svc(argp, res, rqstp)
2305 gss_inquire_cred_by_mech_arg *argp;
2306 gss_inquire_cred_by_mech_res *res;
2307 struct svc_req *rqstp;
2308 {
2309 
2310 	uid_t uid;
2311 
2312 	gss_cred_id_t cred_handle;
2313 	gss_OID_desc		mech_type_desc;
2314 	gss_OID 		mech_type = &mech_type_desc;
2315 
2316 	memset(res, 0, sizeof (*res));
2317 
2318 	if (gssd_debug)
2319 		fprintf(stderr, gettext("gss_inquire_cred\n"));
2320 
2321 	/* verify the verifier_cred_handle */
2322 
2323 	if (argp->gssd_cred_verifier != gssd_time_verf) {
2324 		res->status = (OM_uint32) GSS_S_DEFECTIVE_CREDENTIAL;
2325 		res->minor_status = 0;
2326 		return (TRUE);
2327 	}
2328 
2329 	/*
2330 	 * if the request isn't from root, null out the result pointer
2331 	 * entries, so the next time through xdr_free won't try to
2332 	 * free unmalloc'd memory and then return NULL
2333 	 */
2334 
2335 	if (checkfrom(rqstp, &uid) == 0) {
2336 		return (FALSE);
2337 	}
2338 
2339 	/* set the uid sent as the RPC argument */
2340 
2341 	uid = argp->uid;
2342 	set_gssd_uid(uid);
2343 
2344 	cred_handle = (argp->cred_handle.GSS_CRED_ID_T_len == 0 ?
2345 			GSS_C_NO_CREDENTIAL :
2346 			/*LINTED*/
2347 			*((gss_cred_id_t *)argp->cred_handle.
2348 				GSS_CRED_ID_T_val));
2349 
2350 	/* call the gssapi routine */
2351 
2352 	if (argp->mech_type.GSS_OID_len == 0)
2353 		mech_type = GSS_C_NULL_OID;
2354 	else {
2355 		mech_type->length =
2356 			(OM_uint32)argp->mech_type.GSS_OID_len;
2357 		mech_type->elements =
2358 			(void *)malloc(mech_type->length);
2359 		if (!mech_type->elements) {
2360 			return (GSS_S_FAILURE);
2361 		}
2362 		memcpy(mech_type->elements,
2363 			argp->mech_type.GSS_OID_val,
2364 			mech_type->length);
2365 	}
2366 	res->status = (OM_uint32)gss_inquire_cred_by_mech(
2367 					&res->minor_status, cred_handle,
2368 					mech_type, NULL, NULL,
2369 					NULL, NULL);
2370 
2371 	/* return to caller */
2372 	return (TRUE);
2373 }
2374 
2375 
2376 bool_t
2377 gsscred_name_to_unix_cred_1_svc(argsp, res, rqstp)
2378 gsscred_name_to_unix_cred_arg *argsp;
2379 gsscred_name_to_unix_cred_res *res;
2380 struct svc_req *rqstp;
2381 {
2382 	uid_t uid;
2383 	gss_OID_desc oid;
2384 	gss_name_t gssName;
2385 	gss_buffer_desc gssBuf = GSS_C_EMPTY_BUFFER;
2386 	OM_uint32 minor;
2387 	int gidsLen;
2388 	gid_t *gids, gidOut;
2389 
2390 	if (gssd_debug)
2391 		fprintf(stderr, gettext("gsscred_name_to_unix_cred\n"));
2392 
2393 	memset(res, 0, sizeof (*res));
2394 
2395 	/*
2396 	 * check the request originator
2397 	 */
2398 	if (checkfrom(rqstp, &uid) == 0)
2399 		return (FALSE);
2400 
2401 	/* set the uid from the rpc request */
2402 	uid = argsp->uid;
2403 	set_gssd_uid(uid);
2404 
2405 	/*
2406 	 * convert the principal name to gss internal format
2407 	 * need not malloc the input parameters
2408 	 */
2409 	gssBuf.length = argsp->pname.GSS_BUFFER_T_len;
2410 	gssBuf.value = (void*)argsp->pname.GSS_BUFFER_T_val;
2411 	oid.length = argsp->name_type.GSS_OID_len;
2412 	oid.elements = (void*)argsp->name_type.GSS_OID_val;
2413 
2414 	res->major = gss_import_name(&minor, &gssBuf, &oid, &gssName);
2415 	if (res->major != GSS_S_COMPLETE)
2416 		return (TRUE);
2417 
2418 	/* retrieve the mechanism type from the arguments */
2419 	oid.length = argsp->mech_type.GSS_OID_len;
2420 	oid.elements = (void*)argsp->mech_type.GSS_OID_val;
2421 
2422 	/* call the gss extensions to map the principal name to unix creds */
2423 	res->major = gsscred_name_to_unix_cred(gssName, &oid, &uid, &gidOut,
2424 					&gids, &gidsLen);
2425 	gss_release_name(&minor, &gssName);
2426 
2427 	if (res->major == GSS_S_COMPLETE) {
2428 		res->uid = uid;
2429 		res->gid = gidOut;
2430 		res->gids.GSSCRED_GIDS_val = gids;
2431 		res->gids.GSSCRED_GIDS_len = gidsLen;
2432 	}
2433 
2434 	return (TRUE);
2435 } /* gsscred_name_to_unix_cred_svc_1 */
2436 
2437 bool_t
2438 gsscred_expname_to_unix_cred_1_svc(argsp, res, rqstp)
2439 gsscred_expname_to_unix_cred_arg *argsp;
2440 gsscred_expname_to_unix_cred_res *res;
2441 struct svc_req *rqstp;
2442 {
2443 	uid_t uid;
2444 	gss_buffer_desc expName = GSS_C_EMPTY_BUFFER;
2445 	int gidsLen;
2446 	gid_t *gids, gidOut;
2447 
2448 	if (gssd_debug)
2449 		fprintf(stderr, gettext("gsscred_expname_to_unix_cred\n"));
2450 
2451 	memset(res, 0, sizeof (*res));
2452 
2453 	/*
2454 	 * check the request originator
2455 	 */
2456 	if (checkfrom(rqstp, &uid) == 0)
2457 		return (FALSE);
2458 
2459 	/* set the uid from the rpc request */
2460 	uid = argsp->uid;
2461 	set_gssd_uid(uid);
2462 
2463 	/*
2464 	 * extract the export name from arguments
2465 	 * need not malloc the input parameters
2466 	 */
2467 	expName.length = argsp->expname.GSS_BUFFER_T_len;
2468 	expName.value = (void*)argsp->expname.GSS_BUFFER_T_val;
2469 
2470 	res->major = gsscred_expname_to_unix_cred(&expName, &uid,
2471 					&gidOut, &gids, &gidsLen);
2472 
2473 	if (res->major == GSS_S_COMPLETE) {
2474 		res->uid = uid;
2475 		res->gid = gidOut;
2476 		res->gids.GSSCRED_GIDS_val = gids;
2477 		res->gids.GSSCRED_GIDS_len = gidsLen;
2478 	}
2479 
2480 	return (TRUE);
2481 } /* gsscred_expname_to_unix_cred_1_svc */
2482 
2483 bool_t
2484 gss_get_group_info_1_svc(argsp, res, rqstp)
2485 gss_get_group_info_arg *argsp;
2486 gss_get_group_info_res *res;
2487 struct svc_req *rqstp;
2488 {
2489 	uid_t uid;
2490 	int gidsLen;
2491 	gid_t *gids, gidOut;
2492 
2493 	if (gssd_debug)
2494 		fprintf(stderr, gettext("gss_get_group_info\n"));
2495 
2496 	memset(res, 0, sizeof (*res));
2497 
2498 	/*
2499 	 * check the request originator
2500 	 */
2501 	if (checkfrom(rqstp, &uid) == 0)
2502 		return (FALSE);
2503 
2504 	/* set the uid from the rpc request */
2505 	uid = argsp->uid;
2506 	set_gssd_uid(uid);
2507 
2508 	/*
2509 	 * extract the uid from the arguments
2510 	 */
2511 	uid = argsp->puid;
2512 	res->major = gss_get_group_info(uid, &gidOut, &gids, &gidsLen);
2513 	if (res->major == GSS_S_COMPLETE) {
2514 		res->gid = gidOut;
2515 		res->gids.GSSCRED_GIDS_val = gids;
2516 		res->gids.GSSCRED_GIDS_len = gidsLen;
2517 	}
2518 
2519 	return (TRUE);
2520 } /* gss_get_group_info_1_svc */
2521 
2522 /*ARGSUSED*/
2523 bool_t
2524 gss_get_kmod_1_svc(argsp, res, rqstp)
2525 	gss_get_kmod_arg *argsp;
2526 	gss_get_kmod_res *res;
2527 	struct svc_req *rqstp;
2528 {
2529 	gss_OID_desc oid;
2530 	char *kmodName;
2531 
2532 	if (gssd_debug)
2533 		fprintf(stderr, gettext("gss_get_kmod\n"));
2534 
2535 	res->module_follow = FALSE;
2536 	oid.length = argsp->mech_oid.GSS_OID_len;
2537 	oid.elements = (void *)argsp->mech_oid.GSS_OID_val;
2538 	kmodName = __gss_get_kmodName(&oid);
2539 
2540 	if (kmodName != NULL) {
2541 		res->module_follow = TRUE;
2542 		res->gss_get_kmod_res_u.modname = kmodName;
2543 	}
2544 
2545 	return (TRUE);
2546 }
2547 
2548 /*
2549  *  Returns 1 if caller is ok, else 0.
2550  *  If caller ok, the uid is returned in uidp.
2551  */
2552 static int
2553 checkfrom(rqstp, uidp)
2554 struct svc_req *rqstp;
2555 uid_t *uidp;
2556 {
2557 	SVCXPRT *xprt = rqstp->rq_xprt;
2558 	struct authunix_parms *aup;
2559 	uid_t uid;
2560 
2561 	/* check client agent uid to ensure it is privileged */
2562 	if (__rpc_get_local_uid(xprt, &uid) < 0) {
2563 		syslog(LOG_ERR, gettext("__rpc_get_local_uid failed %s %s"),
2564 			xprt->xp_netid, xprt->xp_tp);
2565 		goto weakauth;
2566 	}
2567 	if (gssd_debug)
2568 		fprintf(stderr, gettext("checkfrom: local_uid  %d\n"), uid);
2569 	if (uid != 0) {
2570 		syslog(LOG_ERR,
2571 			gettext("checkfrom: caller (uid %d) not privileged"),
2572 			uid);
2573 		goto weakauth;
2574 	}
2575 
2576 	/*
2577 	 *  Request came from local privileged process.
2578 	 *  Proceed to get uid of client if needed by caller.
2579 	 */
2580 	if (uidp) {
2581 		if (rqstp->rq_cred.oa_flavor != AUTH_SYS) {
2582 		syslog(LOG_ERR, gettext("checkfrom: not UNIX credentials"));
2583 			goto weakauth;
2584 		}
2585 		/*LINTED*/
2586 		aup = (struct authunix_parms *)rqstp->rq_clntcred;
2587 		*uidp = aup->aup_uid;
2588 		if (gssd_debug) {
2589 			fprintf(stderr,
2590 				gettext("checkfrom: caller's uid %d\n"), *uidp);
2591 		}
2592 	}
2593 	return (1);
2594 
2595 	weakauth:
2596 	svcerr_weakauth(xprt);
2597 	return (0);
2598 }
2599