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