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