xref: /titanic_50/usr/src/cmd/gss/gssd/gssd_proc.c (revision 554ff184129088135ad2643c1c9832174a17be88)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  *  RPC server procedures for the gssapi usermode daemon gssd.
31  */
32 
33 #include <stdio.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 	}
107 
108 	gssd_ctx_slot_tbl = (struct gssd_ctx_slot *)
109 		malloc(sizeof (struct gssd_ctx_slot) * max_contexts);
110 
111 	if (gssd_ctx_slot_tbl == NULL) {
112 		(void) fprintf(stderr,
113 			gettext("[%s] could not allocate %d byte context table"
114 			"\n"), arg,
115 			(sizeof (struct gssd_ctx_slot) * max_contexts));
116 		exit(1);
117 	}
118 
119 	for (i = 1; i < max_contexts; i++) {
120 		gssd_ctx_slot_tbl[i-1].lru_next = &gssd_ctx_slot_tbl[i];
121 		gssd_ctx_slot_tbl[i].lru_prev = &gssd_ctx_slot_tbl[i-1];
122 		gssd_ctx_slot_tbl[i].inuse = FALSE;
123 		gssd_ctx_slot_tbl[i].verf = 0;
124 		gssd_ctx_slot_tbl[i].create_time = 0;
125 		gssd_ctx_slot_tbl[i].rpcctx = (gss_ctx_id_t)(i + 1);
126 	}
127 
128 	gssd_ctx_slot_tbl[max_contexts - 1].lru_next = &gssd_ctx_slot_tbl[0];
129 	gssd_ctx_slot_tbl[0].lru_prev = &gssd_ctx_slot_tbl[max_contexts - 1];
130 	gssd_ctx_slot_tbl[0].inuse = FALSE;
131 	gssd_ctx_slot_tbl[0].verf = 0;
132 	gssd_ctx_slot_tbl[0].create_time = 0;
133 	gssd_ctx_slot_tbl[0].rpcctx = (gss_ctx_id_t)1;
134 
135 	gssd_lru_head = &gssd_ctx_slot_tbl[0];
136 }
137 
138 static OM_uint32 syslog_interval = 60;
139 
140 static struct gssd_ctx_slot *
141 gssd_alloc_slot(gss_ctx_id_t ctx)
142 {
143 	struct gssd_ctx_slot *lru;
144 	OM_uint32 current_time;
145 	static OM_uint32 last_syslog = 0;
146 	static bool_t first_take = TRUE;
147 	static int tooks;
148 	OM_uint32 minor_status;
149 
150 	lru = gssd_lru_head;
151 	gssd_lru_head = lru->lru_next;
152 
153 	current_time = (OM_uint32) time(NULL);
154 
155 	if (last_syslog == 0)
156 		last_syslog = current_time;	/* Save 1st alloc time */
157 
158 	if (lru->inuse) {
159 		if (lru->ctx != GSS_C_NO_CONTEXT)
160 			(void) gss_delete_sec_context(&minor_status,
161 				&lru->ctx, NULL);
162 		tooks++;
163 
164 		if (((current_time - last_syslog) > syslog_interval) ||
165 			first_take) {
166 			syslog(LOG_WARNING, gettext("re-used an existing "
167 				"context slot of age %u seconds (%d slots re-"
168 				"used during last %u seconds)"),
169 				current_time - lru->create_time, tooks,
170 				current_time - last_syslog);
171 
172 			last_syslog = current_time;
173 			tooks = 0;
174 			first_take = FALSE;
175 		}
176 	}
177 
178 	/*
179 	 * Assign the next context verifier to the context (avoiding zero).
180 	 */
181 	context_verf++;
182 	if (context_verf == 0)
183 		context_verf = 1;
184 	lru->verf = context_verf;
185 
186 	lru->create_time = current_time;
187 	lru->ctx = ctx;
188 	lru->inuse = TRUE;
189 	return (lru);
190 }
191 
192 /*
193  * We always add 1 because we don't want slot 0 to be confused
194  * with GSS_C_NO_CONTEXT.
195  */
196 
197 static struct gssd_ctx_slot *
198 gssd_handle_to_slot(GSS_CTX_ID_T *h)
199 {
200 	intptr_t i;
201 
202 	if (h->GSS_CTX_ID_T_len == 0) {
203 		return (NULL);
204 	}
205 	if (h->GSS_CTX_ID_T_len != sizeof (i))
206 		return (NULL);
207 
208 	i = (*(intptr_t *)(h->GSS_CTX_ID_T_val)) - 1;
209 
210 	if (i < 0 || i >= max_contexts)
211 		return (NULL);
212 
213 	return (&gssd_ctx_slot_tbl[i]);
214 }
215 
216 static void
217 gssd_rel_slot(struct gssd_ctx_slot *lru)
218 {
219 	struct gssd_ctx_slot *prev, *next;
220 
221 	if (lru == NULL)
222 		return;
223 
224 	lru->inuse = FALSE;
225 
226 	/*
227 	 * Remove entry from its current location in list
228 	 */
229 	prev = lru->lru_prev;
230 	next = lru->lru_next;
231 	prev->lru_next = next;
232 	next->lru_prev = prev;
233 
234 	/*
235 	 * Since it is no longer in use, it is the least recently
236 	 * used.
237 	 */
238 	prev = gssd_lru_head->lru_prev;
239 	next = gssd_lru_head;
240 
241 	prev->lru_next = lru;
242 	lru->lru_prev = prev;
243 
244 	next->lru_prev = lru;
245 	lru->lru_next = next;
246 
247 	gssd_lru_head = lru;
248 }
249 
250 static void
251 gssd_convert_context_handle(GSS_CTX_ID_T *h,
252 	gss_ctx_id_t *context_handle,
253 	OM_uint32 verf,
254 	bool_t *context_verf_ok,
255 	struct gssd_ctx_slot **slotp)
256 {
257 	struct gssd_ctx_slot *slot;
258 
259 	*context_verf_ok = FALSE;
260 	*context_handle = (gss_ctx_id_t)1;
261 	if (slotp != NULL)
262 		*slotp = NULL;
263 
264 	if (h->GSS_CTX_ID_T_len == 0) {
265 		*context_handle = GSS_C_NO_CONTEXT;
266 		*context_verf_ok = TRUE;
267 		return;
268 	}
269 
270 	slot = gssd_handle_to_slot(h);
271 
272 	if (slot == NULL)
273 		return;
274 
275 	if (verf != slot->verf)
276 		return;
277 
278 	*context_verf_ok = TRUE;
279 	*context_handle = slot->ctx;
280 	if (slotp != NULL)
281 		*slotp = slot;
282 }
283 
284 bool_t
285 gss_acquire_cred_1_svc(argp, res, rqstp)
286 	gss_acquire_cred_arg *argp;
287 	gss_acquire_cred_res *res;
288 	struct svc_req *rqstp;
289 {
290 	OM_uint32 		minor_status;
291 	gss_name_t		desired_name;
292 	gss_OID_desc		name_type_desc;
293 	gss_OID			name_type = &name_type_desc;
294 	OM_uint32		time_req;
295 	gss_OID_set_desc	desired_mechs_desc;
296 	gss_OID_set		desired_mechs;
297 	int			cred_usage;
298 	gss_cred_id_t 		output_cred_handle;
299 	gss_OID_set 		actual_mechs;
300 	gss_buffer_desc		external_name;
301 	uid_t			uid;
302 	int			i, j;
303 
304 	if (gssd_debug)
305 		fprintf(stderr, gettext("gss_acquire_cred\n"));
306 
307 	memset(res, 0, sizeof (*res));
308 
309 	/*
310 	 * if the request isn't from root, null out the result pointer
311 	 * entries, so the next time through xdr_free won't try to
312 	 * free unmalloc'd memory and then return NULL
313 	 */
314 
315 	if (checkfrom(rqstp, &uid) == 0) {
316 		res->output_cred_handle.GSS_CRED_ID_T_val = NULL;
317 		res->actual_mechs.GSS_OID_SET_val = NULL;
318 		return (FALSE);
319 	}
320 
321 /* set the uid sent as the RPC argument */
322 
323 	uid = argp->uid;
324 	set_gssd_uid(uid);
325 
326 /* convert the desired name from external to internal format */
327 
328 	external_name.length = argp->desired_name.GSS_BUFFER_T_len;
329 	external_name.value = (void *)malloc(external_name.length);
330 	if (!external_name.value)
331 		return (GSS_S_FAILURE);
332 	memcpy(external_name.value, argp->desired_name.GSS_BUFFER_T_val,
333 		external_name.length);
334 
335 	if (argp->name_type.GSS_OID_len == 0) {
336 		name_type = GSS_C_NULL_OID;
337 	} else {
338 		name_type->length = argp->name_type.GSS_OID_len;
339 		name_type->elements = (void *)malloc(name_type->length);
340 		if (!name_type->elements) {
341 			free(external_name.value);
342 			return (GSS_S_FAILURE);
343 		}
344 		memcpy(name_type->elements, argp->name_type.GSS_OID_val,
345 			name_type->length);
346 	}
347 
348 	if (gss_import_name(&minor_status, &external_name, name_type,
349 			    &desired_name) != GSS_S_COMPLETE) {
350 
351 		res->status = (OM_uint32) GSS_S_FAILURE;
352 		res->minor_status = minor_status;
353 
354 		free(external_name.value);
355 		if (name_type != GSS_C_NULL_OID)
356 			free(name_type->elements);
357 
358 		return (TRUE);
359 	}
360 
361 /*
362  * copy the XDR structured arguments into their corresponding local GSSAPI
363  * variables.
364  */
365 
366 	cred_usage = argp->cred_usage;
367 	time_req = argp->time_req;
368 
369 	if (argp->desired_mechs.GSS_OID_SET_len != 0) {
370 		desired_mechs = &desired_mechs_desc;
371 		desired_mechs->count =
372 			(int)argp->desired_mechs.GSS_OID_SET_len;
373 		desired_mechs->elements = (gss_OID)
374 			malloc(sizeof (gss_OID_desc) * desired_mechs->count);
375 		if (!desired_mechs->elements) {
376 			free(external_name.value);
377 			free(name_type->elements);
378 			return (GSS_S_FAILURE);
379 		}
380 		for (i = 0; i < desired_mechs->count; i++) {
381 			desired_mechs->elements[i].length =
382 				(OM_uint32)argp->desired_mechs.
383 				GSS_OID_SET_val[i].GSS_OID_len;
384 			desired_mechs->elements[i].elements =
385 				(void *)malloc(desired_mechs->elements[i].
386 						length);
387 			if (!desired_mechs->elements[i].elements) {
388 				free(external_name.value);
389 				free(name_type->elements);
390 				for (j = 0; j < (i -1); j++) {
391 					free
392 					(desired_mechs->elements[j].elements);
393 				}
394 				free(desired_mechs->elements);
395 				return (GSS_S_FAILURE);
396 			}
397 			memcpy(desired_mechs->elements[i].elements,
398 				argp->desired_mechs.GSS_OID_SET_val[i].
399 				GSS_OID_val,
400 				desired_mechs->elements[i].length);
401 		}
402 	} else
403 		desired_mechs = GSS_C_NULL_OID_SET;
404 
405 	/* call the gssapi routine */
406 
407 	res->status = (OM_uint32)gss_acquire_cred(&res->minor_status,
408 				desired_name,
409 				time_req,
410 				desired_mechs,
411 				cred_usage,
412 				&output_cred_handle,
413 				&actual_mechs,
414 				&res->time_rec);
415 
416 	/*
417 	 * convert the output args from the parameter given in the call to the
418 	 * variable in the XDR result
419 	 */
420 
421 	res->output_cred_handle.GSS_CRED_ID_T_len = sizeof (gss_cred_id_t);
422 	res->output_cred_handle.GSS_CRED_ID_T_val =
423 		(void *)malloc(sizeof (gss_cred_id_t));
424 	if (!res->output_cred_handle.GSS_CRED_ID_T_val) {
425 		free(external_name.value);
426 		free(name_type->elements);
427 		for (i = 0; i < desired_mechs->count; i++) {
428 			free(desired_mechs->elements[i].elements);
429 			}
430 		free(desired_mechs->elements);
431 		return (GSS_S_FAILURE);
432 	}
433 	memcpy(res->output_cred_handle.GSS_CRED_ID_T_val, &output_cred_handle,
434 		sizeof (gss_cred_id_t));
435 
436 	if (actual_mechs != GSS_C_NULL_OID_SET) {
437 		res->actual_mechs.GSS_OID_SET_len =
438 			(uint_t)actual_mechs->count;
439 		res->actual_mechs.GSS_OID_SET_val = (GSS_OID *)
440 			malloc(sizeof (GSS_OID) * actual_mechs->count);
441 		if (!res->actual_mechs.GSS_OID_SET_val) {
442 			free(external_name.value);
443 			free(name_type->elements);
444 			for (i = 0; i < desired_mechs->count; i++) {
445 				free(desired_mechs->elements[i].elements);
446 			}
447 			free(desired_mechs->elements);
448 			free(res->output_cred_handle.GSS_CRED_ID_T_val);
449 			return (GSS_S_FAILURE);
450 		}
451 		for (i = 0; i < actual_mechs->count; i++) {
452 			res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_len =
453 				(uint_t)actual_mechs->elements[i].length;
454 			res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val =
455 				(char *)malloc(actual_mechs->elements[i].
456 						length);
457 			if (!res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val) {
458 				free(external_name.value);
459 				free(name_type->elements);
460 				free(desired_mechs->elements);
461 				for (j = 0; j < desired_mechs->count; j++) {
462 					free
463 					(desired_mechs->elements[i].elements);
464 				}
465 				free(res->actual_mechs.GSS_OID_SET_val);
466 				for (j = 0; j < (i - 1); j++) {
467 					free
468 					(res->actual_mechs.
469 						GSS_OID_SET_val[j].GSS_OID_val);
470 				}
471 				return (GSS_S_FAILURE);
472 			}
473 			memcpy(res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val,
474 				actual_mechs->elements[i].elements,
475 				actual_mechs->elements[i].length);
476 		}
477 	} else
478 		res->actual_mechs.GSS_OID_SET_len = 0;
479 
480 	/*
481 	 * set the time verifier for credential handle.  To ensure that the
482 	 * timestamp is not the same as previous gssd process, verify that
483 	 * time is not the same as set earlier at start of process.  If it
484 	 * is, sleep one second and reset. (due to one second granularity)
485 	 */
486 
487 	if (res->status == GSS_S_COMPLETE) {
488 		res->gssd_cred_verifier = (OM_uint32)time(NULL);
489 		if (res->gssd_cred_verifier == gssd_time_verf) {
490 			sleep(1);
491 			gssd_time_verf = (OM_uint32)time(NULL);
492 		}
493 		res->gssd_cred_verifier = gssd_time_verf;
494 	}
495 
496 	/*
497 	 * now release the space allocated by the underlying gssapi mechanism
498 	 * library for actual_mechs as well as by this routine for
499 	 * external_name, name_type and desired_name
500 	 */
501 
502 	free(external_name.value);
503 	if (name_type != GSS_C_NULL_OID)
504 		free(name_type->elements);
505 	gss_release_name(&minor_status, &desired_name);
506 
507 	if (actual_mechs != GSS_C_NULL_OID_SET) {
508 		for (i = 0; i < actual_mechs->count; i++)
509 			free(actual_mechs->elements[i].elements);
510 		free(actual_mechs->elements);
511 		free(actual_mechs);
512 	}
513 
514 	if (desired_mechs != GSS_C_NULL_OID_SET) {
515 		for (i = 0; i < desired_mechs->count; i++)
516 			free(desired_mechs->elements[i].elements);
517 		free(desired_mechs->elements);
518 
519 	}
520 
521 /* return to caller */
522 
523 	return (TRUE);
524 }
525 
526 bool_t
527 gss_add_cred_1_svc(argp, res, rqstp)
528 	gss_add_cred_arg *argp;
529 	gss_add_cred_res *res;
530 	struct svc_req *rqstp;
531 {
532 
533 	OM_uint32 		minor_status;
534 	gss_name_t		desired_name;
535 	gss_OID_desc		name_type_desc;
536 	gss_OID			name_type = &name_type_desc;
537 	gss_OID_desc		desired_mech_type_desc;
538 	gss_OID			desired_mech_type = &desired_mech_type_desc;
539 	int			cred_usage;
540 	gss_cred_id_t 		input_cred_handle;
541 	gss_OID_set 		actual_mechs;
542 	gss_buffer_desc		external_name;
543 	uid_t			uid;
544 	int			i, j;
545 
546 	if (gssd_debug)
547 		fprintf(stderr, gettext("gss_add_cred\n"));
548 
549 	if (argp->gssd_cred_verifier != gssd_time_verf) {
550 		res->status = (OM_uint32)GSS_S_DEFECTIVE_CREDENTIAL;
551 		res->minor_status = 0;
552 		res->actual_mechs.GSS_OID_SET_len = 0;
553 		res->actual_mechs.GSS_OID_SET_val = NULL;
554 		res->initiator_time_rec = 0;
555 		res->acceptor_time_rec = 0;
556 		fprintf(stderr, gettext("gss_add_cred defective cred\n"));
557 		return (TRUE);
558 	}
559 	memset(res, 0, sizeof (*res));
560 
561 	/*
562 	 * if the request isn't from root, null out the result pointer
563 	 * entries, so the next time through xdr_free won't try to
564 	 * free unmalloc'd memory and then return NULL
565 	 */
566 
567 	if (checkfrom(rqstp, &uid) == 0) {
568 		return (FALSE);
569 	}
570 
571 /* set the uid sent as the RPC argument */
572 
573 	uid = argp->uid;
574 	set_gssd_uid(uid);
575 
576 /* convert the desired name from external to internal format */
577 
578 	external_name.length = argp->desired_name.GSS_BUFFER_T_len;
579 	external_name.value = (void *)argp->desired_name.GSS_BUFFER_T_val;
580 	name_type->length = argp->name_type.GSS_OID_len;
581 	name_type->elements = (void *)argp->name_type.GSS_OID_val;
582 
583 	if (gss_import_name(&minor_status, &external_name, name_type,
584 			    &desired_name) != GSS_S_COMPLETE) {
585 
586 		if (gssd_debug)
587 			fprintf(stderr,
588 				gettext("gss_add_cred:import name"),
589 				gettext(" failed status %d \n"),
590 				res->status);
591 		res->status = (OM_uint32)GSS_S_FAILURE;
592 		res->minor_status = minor_status;
593 		return (TRUE);
594 	}
595 
596 /*
597  * copy the XDR structured arguments into their corresponding local GSSAPI
598  * variables.
599  */
600 
601 	cred_usage = argp->cred_usage;
602 	if (argp->desired_mech_type.GSS_OID_len == 0)
603 		desired_mech_type = GSS_C_NULL_OID;
604 	else {
605 		desired_mech_type->length =
606 			(OM_uint32)argp->desired_mech_type.GSS_OID_len;
607 		desired_mech_type->elements =
608 			(void *)malloc(desired_mech_type->length);
609 		if (!desired_mech_type->elements) {
610 			return (GSS_S_FAILURE);
611 		}
612 		memcpy(desired_mech_type->elements,
613 			argp->desired_mech_type.GSS_OID_val,
614 			desired_mech_type->length);
615 	}
616 	input_cred_handle =
617 		(argp->input_cred_handle.GSS_CRED_ID_T_len == 0 ?
618 			GSS_C_NO_CREDENTIAL :
619 			/*LINTED*/
620 			*((gss_cred_id_t *)argp->input_cred_handle.
621 				GSS_CRED_ID_T_val));
622 
623 	if (input_cred_handle != GSS_C_NO_CREDENTIAL)
624 	/* verify the input_cred_handle */
625 		if (argp->gssd_cred_verifier != gssd_time_verf) {
626 			res->status = (OM_uint32)GSS_S_DEFECTIVE_CREDENTIAL;
627 			res->minor_status = 0;
628 			return (TRUE);
629 		}
630 
631 	/* call the gssapi routine */
632 
633 	res->status = (OM_uint32)gss_add_cred(&res->minor_status,
634 				input_cred_handle,
635 				desired_name,
636 				desired_mech_type,
637 				cred_usage,
638 				argp->initiator_time_req,
639 				argp->acceptor_time_req,
640 				NULL,
641 				&actual_mechs,
642 				&res->initiator_time_rec,
643 				&res->acceptor_time_rec);
644 
645 	if ((res->status != GSS_S_COMPLETE) &&
646 		(res->status != GSS_S_DUPLICATE_ELEMENT) &&
647 		(gssd_debug))
648 		fprintf(stderr, gettext("gss_add_cred failed status %d \n"),
649 			res->status);
650 	/*
651 	 * convert the output args from the parameter given in the call to the
652 	 * variable in the XDR result
653 	 */
654 	if (actual_mechs != GSS_C_NULL_OID_SET) {
655 		res->actual_mechs.GSS_OID_SET_len =
656 			(uint_t)actual_mechs->count;
657 		res->actual_mechs.GSS_OID_SET_val = (GSS_OID *)
658 			malloc(sizeof (GSS_OID) * actual_mechs->count);
659 		if (!res->actual_mechs.GSS_OID_SET_val) {
660 			free(desired_mech_type->elements);
661 			free(desired_mech_type);
662 			return (GSS_S_FAILURE);
663 		}
664 		for (i = 0; i < actual_mechs->count; i++) {
665 			res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_len =
666 				(uint_t)actual_mechs->elements[i].length;
667 			res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val =
668 				(char *)malloc(actual_mechs->elements[i].
669 						length);
670 			if (!res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val) {
671 				free(desired_mech_type->elements);
672 				free(desired_mech_type);
673 				free(res->actual_mechs.GSS_OID_SET_val);
674 				for (j = 0; j < (i - 1); j++) {
675 					free
676 					(res->actual_mechs.
677 						GSS_OID_SET_val[j].GSS_OID_val);
678 				}
679 				return (GSS_S_FAILURE);
680 			}
681 			memcpy(res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val,
682 				actual_mechs->elements[i].elements,
683 				actual_mechs->elements[i].length);
684 		}
685 	} else
686 		res->actual_mechs.GSS_OID_SET_len = 0;
687 
688 	/*
689 	 * now release the space allocated for
690 	 * desired_name  and desired_mech_type
691 	 */
692 
693 	gss_release_name(&minor_status, &desired_name);
694 	free(desired_mech_type->elements);
695 	gss_release_oid_set(&minor_status, &actual_mechs);
696 	/*
697 	 * if (actual_mechs != GSS_C_NULL_OID_SET) {
698 	 * 	for (i = 0; i < actual_mechs->count; i++)
699 	 * 		free(actual_mechs->elements[i].elements);
700 	 * 	free(actual_mechs->elements);
701 	 * 	free(actual_mechs);
702 	 * }
703 	 */
704 
705 
706 /* return to caller */
707 
708 	return (TRUE);
709 }
710 
711 bool_t
712 gss_release_cred_1_svc(argp, res, rqstp)
713 gss_release_cred_arg *argp;
714 gss_release_cred_res *res;
715 struct svc_req *rqstp;
716 {
717 
718 	uid_t uid;
719 	gss_cred_id_t cred_handle;
720 
721 	memset(res, 0, sizeof (*res));
722 
723 	if (gssd_debug)
724 		fprintf(stderr, gettext("gss_release_cred\n"));
725 
726 	if (checkfrom(rqstp, &uid) == 0)
727 		return (FALSE);
728 
729 	/* set the uid sent as the RPC argument */
730 
731 	uid = argp->uid;
732 	set_gssd_uid(uid);
733 
734 	/*
735 	 * if the cred_handle verifier is not correct,
736 	 * set status to GSS_S_DEFECTIVE_CREDENTIAL and return
737 	 */
738 
739 	if (argp->gssd_cred_verifier != gssd_time_verf) {
740 		res->status = (OM_uint32)GSS_S_DEFECTIVE_CREDENTIAL;
741 		return (TRUE);
742 	}
743 
744 	/*
745 	 * if the cred_handle length is 0
746 	 * set cred_handle argument to GSS_S_NO_CREDENTIAL
747 	 */
748 
749 	if (argp->cred_handle.GSS_CRED_ID_T_len == 0)
750 		cred_handle = GSS_C_NO_CREDENTIAL;
751 	else
752 		cred_handle =
753 		(gss_cred_id_t)argp->cred_handle.GSS_CRED_ID_T_val;
754 
755 	/* call the gssapi routine */
756 
757 	res->status = (OM_uint32)gss_release_cred(&res->minor_status,
758 					&cred_handle);
759 
760 	/* return to caller */
761 
762 	return (TRUE);
763 }
764 
765 bool_t
766 gss_init_sec_context_1_svc(argp, res, rqstp)
767 gss_init_sec_context_arg *argp;
768 gss_init_sec_context_res *res;
769 struct svc_req *rqstp;
770 {
771 
772 	OM_uint32 	minor_status;
773 	gss_ctx_id_t	context_handle;
774 	bool_t context_verf_ok;
775 	gss_cred_id_t	claimant_cred_handle;
776 	gss_buffer_desc	external_name;
777 	gss_OID_desc	name_type_desc;
778 	gss_OID		name_type = &name_type_desc;
779 	gss_name_t	internal_name;
780 
781 	gss_OID_desc	mech_type_desc;
782 	gss_OID		mech_type = &mech_type_desc;
783 	struct gss_channel_bindings_struct
784 			input_chan_bindings;
785 	gss_channel_bindings_t input_chan_bindings_ptr;
786 	gss_buffer_desc input_token;
787 	gss_buffer_desc output_token;
788 	gss_buffer_t input_token_ptr;
789 	gss_OID actual_mech_type;
790 	struct gssd_ctx_slot *slot = NULL;
791 
792 	uid_t uid;
793 
794 	memset(res, 0, sizeof (*res));
795 
796 	if (gssd_debug)
797 		fprintf(stderr, gettext("gss_init_sec_context\n"));
798 
799 	/*
800 	 * if the request isn't from root, null out the result pointer
801 	 * entries, so the next time through xdr_free won't try to
802 	 * free unmalloc'd memory and then return NULL
803 	 */
804 
805 	if (checkfrom(rqstp, &uid) == 0) {
806 		res->context_handle.GSS_CTX_ID_T_val =  NULL;
807 		res->actual_mech_type.GSS_OID_val = NULL;
808 		res->output_token.GSS_BUFFER_T_val = NULL;
809 		return (FALSE);
810 	}
811 
812 /* set the uid sent as the RPC argument */
813 
814 	uid = argp->uid;
815 	set_gssd_uid(uid);
816 
817 /*
818  * copy the supplied context handle into the local context handle, so it
819  * can be supplied to the gss_init_sec_context call
820  */
821 
822 	gssd_convert_context_handle(&argp->context_handle, &context_handle,
823 		argp->gssd_context_verifier, &context_verf_ok, &slot);
824 
825 	claimant_cred_handle =
826 		(argp->claimant_cred_handle.GSS_CRED_ID_T_len == 0 ?
827 		GSS_C_NO_CREDENTIAL :
828 		/*LINTED*/
829 		*((gss_cred_id_t *)argp->claimant_cred_handle.
830 			GSS_CRED_ID_T_val));
831 
832 	if (claimant_cred_handle != GSS_C_NO_CREDENTIAL) {
833 		/* verify the verifier_cred_handle */
834 		if (argp->gssd_cred_verifier != gssd_time_verf) {
835 			res->context_handle.GSS_CTX_ID_T_val = NULL;
836 			res->output_token.GSS_BUFFER_T_val = NULL;
837 			res->actual_mech_type.GSS_OID_val = NULL;
838 			res->context_handle.GSS_CTX_ID_T_len = 0;
839 			res->output_token.GSS_BUFFER_T_len = 0;
840 			res->actual_mech_type.GSS_OID_len = 0;
841 			res->status = (OM_uint32)GSS_S_DEFECTIVE_CREDENTIAL;
842 			res->minor_status = 0;
843 			return (TRUE);
844 		}
845 	}
846 
847 	if (context_handle != GSS_C_NO_CONTEXT) {
848 		/* verify the verifier_context_handle */
849 
850 		if (!context_verf_ok) {
851 			res->context_handle.GSS_CTX_ID_T_val = NULL;
852 			res->output_token.GSS_BUFFER_T_val = NULL;
853 			res->actual_mech_type.GSS_OID_val = NULL;
854 			res->context_handle.GSS_CTX_ID_T_len = 0;
855 			res->output_token.GSS_BUFFER_T_len = 0;
856 			res->actual_mech_type.GSS_OID_len = 0;
857 			res->status = (OM_uint32)GSS_S_NO_CONTEXT;
858 			res->minor_status = 0;
859 			return (TRUE);
860 		}
861 	}
862 
863 	/* convert the target name from external to internal format */
864 
865 	external_name.length = argp->target_name.GSS_BUFFER_T_len;
866 	external_name.value = (void *)argp->target_name.GSS_BUFFER_T_val;
867 
868 	if (argp->name_type.GSS_OID_len == 0) {
869 		name_type = GSS_C_NULL_OID;
870 	} else {
871 		name_type->length = argp->name_type.GSS_OID_len;
872 		name_type->elements = (void *)malloc(name_type->length);
873 		if (!name_type->elements)
874 			return (GSS_S_FAILURE);
875 		memcpy(name_type->elements, argp->name_type.GSS_OID_val,
876 			name_type->length);
877 	}
878 
879 	if (argp->mech_type.GSS_OID_len == 0)
880 		mech_type = GSS_C_NULL_OID;
881 	else {
882 		mech_type->length = (OM_uint32)argp->mech_type.GSS_OID_len;
883 		mech_type->elements = (void *)argp->mech_type.GSS_OID_val;
884 	}
885 
886 	if (gss_import_name(&minor_status, &external_name, name_type,
887 			    &internal_name) != GSS_S_COMPLETE) {
888 
889 		if (name_type != GSS_C_NULL_OID)
890 			free(name_type->elements);
891 		res->status = (OM_uint32)GSS_S_FAILURE;
892 		res->minor_status = minor_status;
893 
894 		return (TRUE);
895 	}
896 /*
897  * copy the XDR structured arguments into their corresponding local GSSAPI
898  * variables.
899  */
900 
901 	if (argp->input_chan_bindings.present == YES) {
902 		input_chan_bindings_ptr = &input_chan_bindings;
903 		input_chan_bindings.initiator_addrtype =
904 			(OM_uint32)argp->input_chan_bindings.
905 			initiator_addrtype;
906 		input_chan_bindings.initiator_address.length =
907 			(uint_t)argp->input_chan_bindings.initiator_address.
908 			GSS_BUFFER_T_len;
909 		input_chan_bindings.initiator_address.value =
910 			(void *)argp->input_chan_bindings.initiator_address.
911 			GSS_BUFFER_T_val;
912 		input_chan_bindings.acceptor_addrtype =
913 			(OM_uint32)argp->input_chan_bindings.acceptor_addrtype;
914 		input_chan_bindings.acceptor_address.length =
915 			(uint_t)argp->input_chan_bindings.acceptor_address.
916 			GSS_BUFFER_T_len;
917 		input_chan_bindings.acceptor_address.value =
918 			(void *)argp->input_chan_bindings.acceptor_address.
919 			GSS_BUFFER_T_val;
920 		input_chan_bindings.application_data.length =
921 			(uint_t)argp->input_chan_bindings.application_data.
922 			GSS_BUFFER_T_len;
923 		input_chan_bindings.application_data.value =
924 			(void *)argp->input_chan_bindings.application_data.
925 			GSS_BUFFER_T_val;
926 	} else {
927 		input_chan_bindings_ptr = GSS_C_NO_CHANNEL_BINDINGS;
928 		input_chan_bindings.initiator_addrtype = 0;
929 		input_chan_bindings.initiator_address.length = 0;
930 		input_chan_bindings.initiator_address.value = 0;
931 		input_chan_bindings.acceptor_addrtype = 0;
932 		input_chan_bindings.acceptor_address.length = 0;
933 		input_chan_bindings.acceptor_address.value = 0;
934 		input_chan_bindings.application_data.length = 0;
935 		input_chan_bindings.application_data.value = 0;
936 	}
937 
938 	if (argp->input_token.GSS_BUFFER_T_len == 0) {
939 		input_token_ptr = GSS_C_NO_BUFFER;
940 	} else {
941 		input_token_ptr = &input_token;
942 		input_token.length = (size_t)
943 				argp->input_token.GSS_BUFFER_T_len;
944 		input_token.value = (void *)argp->input_token.GSS_BUFFER_T_val;
945 	}
946 
947 /* call the gssapi routine */
948 
949 	res->status = (OM_uint32)gss_init_sec_context(&res->minor_status,
950 			(gss_cred_id_t)argp->claimant_cred_handle.
951 						GSS_CRED_ID_T_val,
952 					&context_handle,
953 					internal_name,
954 					mech_type,
955 					argp->req_flags,
956 					argp->time_req,
957 					input_chan_bindings_ptr,
958 					input_token_ptr,
959 					&actual_mech_type,
960 					&output_token,
961 					&res->ret_flags,
962 					&res->time_rec);
963 
964 	/*
965 	 * convert the output args from the parameter given in the call to the
966 	 * variable in the XDR result
967 	 */
968 
969 	if (res->status == (OM_uint32)GSS_S_COMPLETE ||
970 		res->status == (OM_uint32)GSS_S_CONTINUE_NEEDED) {
971 
972 		if (slot == NULL || slot->ctx != context_handle) {
973 			/*
974 			 * Note that gssd_alloc_slot() will delete ctx's as long
975 			 * as we don't call gssd_rel_slot().
976 			 */
977 			slot = gssd_alloc_slot(context_handle);
978 		}
979 
980 		res->gssd_context_verifier = slot->verf;
981 
982 		res->context_handle.GSS_CTX_ID_T_len = sizeof (gss_ctx_id_t);
983 		res->context_handle.GSS_CTX_ID_T_val =
984 			(void *)malloc(sizeof (gss_ctx_id_t));
985 		if (!res->context_handle.GSS_CTX_ID_T_val) {
986 			free(name_type->elements);
987 			return (GSS_S_FAILURE);
988 		}
989 
990 		memcpy(res->context_handle.GSS_CTX_ID_T_val, &slot->rpcctx,
991 			sizeof (gss_ctx_id_t));
992 
993 		res->output_token.GSS_BUFFER_T_len =
994 			(uint_t)output_token.length;
995 		res->output_token.GSS_BUFFER_T_val =
996 			(char *)output_token.value;
997 
998 		/*
999 		 * the actual mech type parameter
1000 		 * is ready only upon GSS_S_COMPLETE
1001 		 */
1002 		if (res->status == GSS_S_COMPLETE) {
1003 			res->actual_mech_type.GSS_OID_len =
1004 				(uint_t)actual_mech_type->length;
1005 			res->actual_mech_type.GSS_OID_val =
1006 				(void *)malloc(actual_mech_type->length);
1007 			if (!res->actual_mech_type.GSS_OID_val) {
1008 				free(name_type->elements);
1009 				free(res->context_handle.GSS_CTX_ID_T_val);
1010 				return (GSS_S_FAILURE);
1011 			}
1012 			memcpy(res->actual_mech_type.GSS_OID_val,
1013 				(char *)actual_mech_type->elements,
1014 				actual_mech_type->length);
1015 		} else
1016 			res->actual_mech_type.GSS_OID_len = 0;
1017 	} else {
1018 		if (context_handle != GSS_C_NO_CONTEXT) {
1019 			(void) gss_delete_sec_context(&minor_status,
1020 				&context_handle, NULL);
1021 		}
1022 		res->context_handle.GSS_CTX_ID_T_len = 0;
1023 		res->actual_mech_type.GSS_OID_len = 0;
1024 		res->output_token.GSS_BUFFER_T_len = 0;
1025 	}
1026 
1027 	/*
1028 	 * now release the space allocated by the underlying gssapi mechanism
1029 	 * library for internal_name and for the name_type.
1030 	 */
1031 
1032 	gss_release_name(&minor_status, &internal_name);
1033 	if (name_type != GSS_C_NULL_OID)
1034 		free(name_type->elements);
1035 
1036 
1037 	/* return to caller */
1038 	return (TRUE);
1039 }
1040 
1041 bool_t
1042 gss_accept_sec_context_1_svc(argp, res, rqstp)
1043 gss_accept_sec_context_arg *argp;
1044 gss_accept_sec_context_res *res;
1045 struct svc_req *rqstp;
1046 {
1047 	uid_t uid;
1048 	OM_uint32 minor_status;
1049 	gss_ctx_id_t context_handle = NULL;
1050 	gss_cred_id_t verifier_cred_handle;
1051 	gss_buffer_desc external_name;
1052 	gss_name_t internal_name = NULL;
1053 
1054 	gss_buffer_desc input_token_buffer;
1055 	gss_buffer_t input_token_buffer_ptr;
1056 	struct gss_channel_bindings_struct
1057 			input_chan_bindings;
1058 	gss_channel_bindings_t input_chan_bindings_ptr;
1059 	gss_OID mech_type;
1060 	gss_buffer_desc output_token;
1061 	gss_cred_id_t delegated_cred_handle;
1062 	bool_t context_verf_ok;
1063 	struct gssd_ctx_slot *slot = NULL;
1064 
1065 	memset(res, 0, sizeof (*res));
1066 
1067 	if (gssd_debug)
1068 		fprintf(stderr, gettext("gss_accept_sec_context\n"));
1069 
1070 	/*
1071 	 * if the request isn't from root, null out the result pointer
1072 	 * entries, so the next time through xdr_free won't try to
1073 	 * free unmalloc'd memory and then return NULL
1074 	 */
1075 
1076 	if (checkfrom(rqstp, &uid) == 0) {
1077 		res->context_handle.GSS_CTX_ID_T_val = NULL;
1078 		res->src_name.GSS_BUFFER_T_val = NULL;
1079 		res->mech_type.GSS_OID_val = NULL;
1080 		res->output_token.GSS_BUFFER_T_val = NULL;
1081 		res->delegated_cred_handle.GSS_CRED_ID_T_val = NULL;
1082 		return (FALSE);
1083 	}
1084 
1085 	/* set the uid sent as the RPC argument */
1086 
1087 	uid = argp->uid;
1088 	set_gssd_uid(uid);
1089 
1090 	/*
1091 	 * copy the supplied context handle into the local context handle, so
1092 	 * it can be supplied to the gss_accept_sec_context call
1093 	 */
1094 
1095 	gssd_convert_context_handle(&argp->context_handle, &context_handle,
1096 		argp->gssd_context_verifier, &context_verf_ok, &slot);
1097 
1098 	if (context_handle != GSS_C_NO_CONTEXT)
1099 		/* verify the context_handle */
1100 		if (!context_verf_ok) {
1101 			res->context_handle.GSS_CTX_ID_T_val = NULL;
1102 			res->src_name.GSS_BUFFER_T_val = NULL;
1103 			res->mech_type.GSS_OID_val = NULL;
1104 			res->output_token.GSS_BUFFER_T_val = NULL;
1105 			res->delegated_cred_handle.GSS_CRED_ID_T_val = NULL;
1106 			res->src_name.GSS_BUFFER_T_len = 0;
1107 			res->context_handle.GSS_CTX_ID_T_len = 0;
1108 			res->delegated_cred_handle.GSS_CRED_ID_T_len = 0;
1109 			res->output_token.GSS_BUFFER_T_len = 0;
1110 			res->mech_type.GSS_OID_len = 0;
1111 			res->status = (OM_uint32)GSS_S_NO_CONTEXT;
1112 			res->minor_status = 0;
1113 			return (TRUE);
1114 		}
1115 
1116 	/*
1117 	 * copy the XDR structured arguments into their corresponding local
1118 	 * GSSAPI variable equivalents.
1119 	 */
1120 
1121 
1122 	verifier_cred_handle =
1123 		(argp->verifier_cred_handle.GSS_CRED_ID_T_len == 0 ?
1124 			GSS_C_NO_CREDENTIAL :
1125 			/*LINTED*/
1126 			*((gss_cred_id_t *)argp->verifier_cred_handle.
1127 				GSS_CRED_ID_T_val));
1128 
1129 	if (verifier_cred_handle != GSS_C_NO_CREDENTIAL)
1130 	/* verify the verifier_cred_handle */
1131 		if (argp->gssd_cred_verifier != gssd_time_verf) {
1132 			res->context_handle.GSS_CTX_ID_T_val = NULL;
1133 			res->src_name.GSS_BUFFER_T_val = NULL;
1134 			res->mech_type.GSS_OID_val = NULL;
1135 			res->output_token.GSS_BUFFER_T_val = NULL;
1136 			res->delegated_cred_handle.GSS_CRED_ID_T_val = NULL;
1137 			res->src_name.GSS_BUFFER_T_len = 0;
1138 			res->context_handle.GSS_CTX_ID_T_len = 0;
1139 			res->delegated_cred_handle.GSS_CRED_ID_T_len = 0;
1140 			res->output_token.GSS_BUFFER_T_len = 0;
1141 			res->mech_type.GSS_OID_len = 0;
1142 			res->status = (OM_uint32)GSS_S_DEFECTIVE_CREDENTIAL;
1143 			res->minor_status = 0;
1144 			return (TRUE);
1145 		}
1146 
1147 	if (argp->input_token_buffer.GSS_BUFFER_T_len == 0) {
1148 		input_token_buffer_ptr = GSS_C_NO_BUFFER;
1149 	} else {
1150 		input_token_buffer_ptr = &input_token_buffer;
1151 		input_token_buffer.length = (size_t)argp->input_token_buffer.
1152 						GSS_BUFFER_T_len;
1153 		input_token_buffer.value = (void *)argp->input_token_buffer.
1154 						GSS_BUFFER_T_val;
1155 	}
1156 
1157 	if (argp->input_chan_bindings.present == YES) {
1158 		input_chan_bindings_ptr = &input_chan_bindings;
1159 		input_chan_bindings.initiator_addrtype =
1160 			(OM_uint32)argp->input_chan_bindings.
1161 					initiator_addrtype;
1162 		input_chan_bindings.initiator_address.length =
1163 			(uint_t)argp->input_chan_bindings.initiator_address.
1164 					GSS_BUFFER_T_len;
1165 		input_chan_bindings.initiator_address.value =
1166 			(void *)argp->input_chan_bindings.initiator_address.
1167 					GSS_BUFFER_T_val;
1168 		input_chan_bindings.acceptor_addrtype =
1169 			(OM_uint32)argp->input_chan_bindings.
1170 					acceptor_addrtype;
1171 		input_chan_bindings.acceptor_address.length =
1172 			(uint_t)argp->input_chan_bindings.acceptor_address.
1173 					GSS_BUFFER_T_len;
1174 		input_chan_bindings.acceptor_address.value =
1175 			(void *)argp->input_chan_bindings.acceptor_address.
1176 					GSS_BUFFER_T_val;
1177 		input_chan_bindings.application_data.length =
1178 			(uint_t)argp->input_chan_bindings.application_data.
1179 					GSS_BUFFER_T_len;
1180 		input_chan_bindings.application_data.value =
1181 			(void *)argp->input_chan_bindings.application_data.
1182 					GSS_BUFFER_T_val;
1183 	} else {
1184 		input_chan_bindings_ptr = GSS_C_NO_CHANNEL_BINDINGS;
1185 		input_chan_bindings.initiator_addrtype = 0;
1186 		input_chan_bindings.initiator_address.length = 0;
1187 		input_chan_bindings.initiator_address.value = 0;
1188 		input_chan_bindings.acceptor_addrtype = 0;
1189 		input_chan_bindings.acceptor_address.length = 0;
1190 		input_chan_bindings.acceptor_address.value = 0;
1191 		input_chan_bindings.application_data.length = 0;
1192 		input_chan_bindings.application_data.value = 0;
1193 	}
1194 
1195 
1196 	/* call the gssapi routine */
1197 
1198 	res->status = (OM_uint32)gss_accept_sec_context(&res->minor_status,
1199 						&context_handle,
1200 						verifier_cred_handle,
1201 						input_token_buffer_ptr,
1202 						input_chan_bindings_ptr,
1203 						&internal_name,
1204 						&mech_type,
1205 						&output_token,
1206 						&res->ret_flags,
1207 						&res->time_rec,
1208 						&delegated_cred_handle);
1209 
1210 	/* convert the src name from internal to external format */
1211 
1212 	if (res->status == (OM_uint32)GSS_S_COMPLETE ||
1213 		res->status == (OM_uint32)GSS_S_CONTINUE_NEEDED) {
1214 
1215 		/*
1216 		 * upon GSS_S_CONTINUE_NEEDED only the following
1217 		 * parameters are ready: minor, ctxt, and output token
1218 		 */
1219 		res->context_handle.GSS_CTX_ID_T_len = sizeof (gss_ctx_id_t);
1220 		res->context_handle.GSS_CTX_ID_T_val =
1221 			(void *)malloc(sizeof (gss_ctx_id_t));
1222 		if (!res->context_handle.GSS_CTX_ID_T_val) {
1223 			res->status = (OM_uint32)GSS_S_FAILURE;
1224 			res->minor_status = 0;
1225 			return (TRUE);
1226 		}
1227 
1228 		if (slot == NULL || slot->ctx != context_handle) {
1229 			/*
1230 			 * Note that gssd_alloc_slot() will delete ctx's as long
1231 			 * as we don't call gssd_rel_slot().
1232 			 */
1233 			slot = gssd_alloc_slot(context_handle);
1234 		}
1235 
1236 		memcpy(res->context_handle.GSS_CTX_ID_T_val, &slot->rpcctx,
1237 			sizeof (gss_ctx_id_t));
1238 		res->gssd_context_verifier = slot->verf;
1239 
1240 		res->output_token.GSS_BUFFER_T_len =
1241 				(uint_t)output_token.length;
1242 		res->output_token.GSS_BUFFER_T_val =
1243 				(char *)output_token.value;
1244 
1245 		if (res->status == GSS_S_COMPLETE) {
1246 			if (gss_export_name(&minor_status, internal_name,
1247 					&external_name)
1248 				!= GSS_S_COMPLETE) {
1249 
1250 				res->status = (OM_uint32)GSS_S_FAILURE;
1251 				res->minor_status = minor_status;
1252 				gss_release_name(&minor_status, &internal_name);
1253 				gss_delete_sec_context(&minor_status,
1254 						&context_handle, NULL);
1255 				free(res->context_handle.GSS_CTX_ID_T_val);
1256 				res->context_handle.GSS_CTX_ID_T_val = NULL;
1257 				res->context_handle.GSS_CTX_ID_T_len = 0;
1258 				gss_release_buffer(&minor_status,
1259 						&output_token);
1260 				res->output_token.GSS_BUFFER_T_len = 0;
1261 				res->output_token.GSS_BUFFER_T_val = NULL;
1262 				return (TRUE);
1263 			}
1264 			res->src_name.GSS_BUFFER_T_len =
1265 				(uint_t)external_name.length;
1266 			res->src_name.GSS_BUFFER_T_val =
1267 				(void *)external_name.value;
1268 
1269 			res->delegated_cred_handle.GSS_CRED_ID_T_len =
1270 				sizeof (gss_cred_id_t);
1271 			res->delegated_cred_handle.GSS_CRED_ID_T_val =
1272 				(void *)malloc(sizeof (gss_cred_id_t));
1273 			if (!res->delegated_cred_handle.GSS_CRED_ID_T_val) {
1274 				free(res->context_handle.GSS_CTX_ID_T_val);
1275 				gss_release_name(&minor_status, &internal_name);
1276 				gss_delete_sec_context(&minor_status,
1277 						&context_handle, NULL);
1278 				gss_release_buffer(&minor_status,
1279 						&external_name);
1280 				res->status = (OM_uint32)GSS_S_FAILURE;
1281 				res->minor_status = 0;
1282 				return (TRUE);
1283 			}
1284 			memcpy(res->delegated_cred_handle.GSS_CRED_ID_T_val,
1285 				&delegated_cred_handle,
1286 				sizeof (gss_cred_id_t));
1287 
1288 			res->mech_type.GSS_OID_len = (uint_t)mech_type->length;
1289 			res->mech_type.GSS_OID_val =
1290 				(void *)malloc(mech_type->length);
1291 			if (!res->mech_type.GSS_OID_val) {
1292 			    free(res->context_handle.GSS_CTX_ID_T_val);
1293 			    free(res->delegated_cred_handle.GSS_CRED_ID_T_val);
1294 			    gss_release_name(&minor_status, &internal_name);
1295 			    gss_delete_sec_context(&minor_status,
1296 						&context_handle, NULL);
1297 			    gss_release_buffer(&minor_status, &external_name);
1298 			    res->status = (OM_uint32)GSS_S_FAILURE;
1299 			    res->minor_status = 0;
1300 			    return (TRUE);
1301 			}
1302 			memcpy(res->mech_type.GSS_OID_val, mech_type->elements,
1303 				mech_type->length);
1304 
1305 			/* release the space allocated for internal_name */
1306 			gss_release_name(&minor_status, &internal_name);
1307 
1308 		} else {    /* GSS_S_CONTINUE_NEEDED */
1309 			res->src_name.GSS_BUFFER_T_len = 0;
1310 			res->delegated_cred_handle.GSS_CRED_ID_T_len = 0;
1311 			res->mech_type.GSS_OID_len = 0;
1312 		}
1313 	} else {
1314 		if (context_handle != GSS_C_NO_CONTEXT) {
1315 			(void) gss_delete_sec_context(&minor_status,
1316 				&context_handle, NULL);
1317 		}
1318 		res->src_name.GSS_BUFFER_T_len = 0;
1319 		res->context_handle.GSS_CTX_ID_T_len = 0;
1320 		res->delegated_cred_handle.GSS_CRED_ID_T_len = 0;
1321 		res->output_token.GSS_BUFFER_T_len = 0;
1322 		res->mech_type.GSS_OID_len = 0;
1323 	}
1324 
1325 /* return to caller */
1326 
1327 	return (TRUE);
1328 }
1329 
1330 bool_t
1331 gss_process_context_token_1_svc(argp, res, rqstp)
1332 gss_process_context_token_arg *argp;
1333 gss_process_context_token_res *res;
1334 struct svc_req *rqstp;
1335 {
1336 
1337 	uid_t uid;
1338 	gss_buffer_desc token_buffer;
1339 	gss_ctx_id_t context_handle;
1340 	bool_t context_verf_ok;
1341 
1342 	memset(res, 0, sizeof (*res));
1343 
1344 	if (gssd_debug)
1345 		fprintf(stderr, gettext("gss_process_context_token\n"));
1346 
1347 	if (checkfrom(rqstp, &uid) == 0)
1348 		return (FALSE);
1349 
1350 	gssd_convert_context_handle(&argp->context_handle, &context_handle,
1351 		argp->gssd_context_verifier, &context_verf_ok, NULL);
1352 
1353 	/* verify the context_handle */
1354 
1355 	if (!context_verf_ok) {
1356 		res->status = (OM_uint32) GSS_S_NO_CONTEXT;
1357 		res->minor_status = 0;
1358 		return (TRUE);
1359 	}
1360 
1361 	/* set the uid sent as the RPC argument */
1362 
1363 	uid = argp->uid;
1364 	set_gssd_uid(uid);
1365 
1366 	/*
1367 	 * copy the XDR structured arguments into their corresponding local
1368 	 * GSSAPI variable equivalents.
1369 	 */
1370 
1371 	token_buffer.length = (size_t)argp->token_buffer.GSS_BUFFER_T_len;
1372 	token_buffer.value = (void *)argp->token_buffer.GSS_BUFFER_T_val;
1373 
1374 
1375 	/* call the gssapi routine */
1376 
1377 	res->status = (OM_uint32)gss_process_context_token(&res->minor_status,
1378 				context_handle,
1379 				&token_buffer);
1380 
1381 
1382 	/* return to caller */
1383 
1384 	return (TRUE);
1385 }
1386 
1387 bool_t
1388 gss_delete_sec_context_1_svc(argp, res, rqstp)
1389 gss_delete_sec_context_arg *argp;
1390 gss_delete_sec_context_res *res;
1391 struct svc_req *rqstp;
1392 {
1393 	uid_t uid;
1394 	gss_ctx_id_t  context_handle;
1395 	gss_buffer_desc output_token;
1396 	bool_t context_verf_ok;
1397 	struct gssd_ctx_slot *slot = NULL;
1398 
1399 	memset(res, 0, sizeof (*res));
1400 
1401 	if (gssd_debug)
1402 		fprintf(stderr, gettext("gss_delete_sec_context\n"));
1403 
1404 
1405 	/*
1406 	 * copy the supplied context handle into the local context handle, so it
1407 	 * can be supplied to the gss_delete_sec_context call
1408 	 */
1409 	gssd_convert_context_handle(&argp->context_handle, &context_handle,
1410 		argp->gssd_context_verifier, &context_verf_ok, &slot);
1411 
1412 	/* verify the context_handle */
1413 	if (!context_verf_ok) {
1414 		res->context_handle.GSS_CTX_ID_T_val = NULL;
1415 		res->context_handle.GSS_CTX_ID_T_len = 0;
1416 		res->output_token.GSS_BUFFER_T_val = NULL;
1417 		res->output_token.GSS_BUFFER_T_len = 0;
1418 		res->status = (OM_uint32)GSS_S_NO_CONTEXT;
1419 		res->minor_status = 0;
1420 		return (TRUE);
1421 	}
1422 
1423 	/*
1424 	 * if the request isn't from root, null out the result pointer
1425 	 * entries, so the next time through xdr_free won't try to
1426 	 * free unmalloc'd memory and then return NULL
1427 	 */
1428 
1429 	if (checkfrom(rqstp, &uid) == 0) {
1430 		res->context_handle.GSS_CTX_ID_T_val = NULL;
1431 		res->output_token.GSS_BUFFER_T_val = NULL;
1432 		return (FALSE);
1433 	}
1434 
1435 	/* call the gssapi routine */
1436 
1437 	res->status = (OM_uint32)gss_delete_sec_context(&res->minor_status,
1438 						&context_handle,
1439 						&output_token);
1440 
1441 	/*
1442 	 * convert the output args from the parameter given in the call to the
1443 	 * variable in the XDR result. If the delete succeeded, return a zero
1444 	 * context handle.
1445 	 */
1446 
1447 	if (res->status == GSS_S_COMPLETE) {
1448 		if (context_handle != GSS_C_NO_CONTEXT)
1449 			return (GSS_S_FAILURE);
1450 		res->context_handle.GSS_CTX_ID_T_len = 0;
1451 		res->context_handle.GSS_CTX_ID_T_val = NULL;
1452 		res->output_token.GSS_BUFFER_T_len =
1453 			(uint_t)output_token.length;
1454 		res->output_token.GSS_BUFFER_T_val =
1455 			(char *)output_token.value;
1456 
1457 		if (slot != NULL) {
1458 			/*
1459 			 * gss_delete_sec_context deletes the context if it
1460 			 * succeeds so clear slot->ctx to avoid a dangling
1461 			 * reference.
1462 			 */
1463 			slot->ctx = GSS_C_NO_CONTEXT;
1464 			gssd_rel_slot(slot);
1465 		}
1466 	} else {
1467 		res->context_handle.GSS_CTX_ID_T_len = sizeof (gss_ctx_id_t);
1468 		res->context_handle.GSS_CTX_ID_T_val =
1469 			(void *)malloc(sizeof (gss_ctx_id_t));
1470 		if (!res->context_handle.GSS_CTX_ID_T_val) {
1471 			return (GSS_S_FAILURE);
1472 		}
1473 
1474 		if (slot == NULL || slot->ctx != context_handle) {
1475 			/*
1476 			 * Note that gssd_alloc_slot() will delete ctx's as long
1477 			 * as we don't call gssd_rel_slot().
1478 			 */
1479 			slot = gssd_alloc_slot(context_handle);
1480 			/*
1481 			 * Note that no verifier is returned in the .x
1482 			 * protocol. So if the context changes, we won't
1483 			 * be able to release it now. So it will have to
1484 			 * be LRUed out.
1485 			 */
1486 		}
1487 
1488 		memcpy(res->context_handle.GSS_CTX_ID_T_val, &slot->rpcctx,
1489 			sizeof (gss_ctx_id_t));
1490 
1491 		res->output_token.GSS_BUFFER_T_len = 0;
1492 		res->output_token.GSS_BUFFER_T_val = NULL;
1493 	}
1494 
1495 	/* return to caller */
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