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