Home | History | Annotate | Download | only in gssapi
      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  *  GSSAPI library stub module for gssd.
     28  */
     29 
     30 #include <mechglueP.h>
     31 #include "gssd_prot.h"
     32 #include <rpc/rpc.h>
     33 
     34 #include <sys/systm.h>
     35 #include <sys/types.h>
     36 #include <sys/cmn_err.h>
     37 #include <sys/kmem.h>
     38 #include <gssapi/kgssapi_defs.h>
     39 #include <sys/debug.h>
     40 
     41 #ifdef GSSDEBUG
     42 /*
     43  * Kernel kgssd module debugging aid. The global variable "gss_log"
     44  * is a bit mask which allows various types of debugging messages
     45  * to be printed out.
     46  *
     47  *	 gss_log & 1  will cause actual failures to be printed.
     48  *	 gss_log & 2  will cause informational messages to be
     49  *	                 printed on the client side of kgssd.
     50  *	 gss_log & 4  will cause informational messages to be
     51  *	                 printed on the server side of kgssd.
     52  *	 gss_log & 8  will cause informational messages to be
     53  *	                 printed on both client and server side of kgssd.
     54  */
     55 
     56 uint_t gss_log = 1;
     57 
     58 #endif /* GSSDEBUG */
     59 
     60 #ifdef  DEBUG
     61 extern void prom_printf();
     62 #endif
     63 
     64 char *server = "localhost";
     65 
     66 static OM_uint32 kgss_sign_wrapped(void *, OM_uint32 *, gss_ctx_id_t, int,
     67 	gss_buffer_t, gss_buffer_t,  OM_uint32);
     68 
     69 static OM_uint32 kgss_verify_wrapped(void *, OM_uint32 *, gss_ctx_id_t,
     70 	gss_buffer_t, gss_buffer_t, int *qop_state, OM_uint32);
     71 
     72 /* EXPORT DELETE START */
     73 static OM_uint32 kgss_seal_wrapped(void *, OM_uint32 *, gss_ctx_id_t,
     74 	int, int, gss_buffer_t, int *, gss_buffer_t,  OM_uint32);
     75 
     76 static OM_uint32 kgss_unseal_wrapped(void *, OM_uint32 *, gss_ctx_id_t,
     77 	gss_buffer_t, gss_buffer_t, int *conf_state, int *qop_state,
     78 	OM_uint32);
     79 /* EXPORT DELETE END */
     80 
     81 static OM_uint32 kgss_delete_sec_context_wrapped(void *, OM_uint32 *,
     82 	gssd_ctx_id_t *, gss_buffer_t, OM_uint32);
     83 
     84 static void __kgss_reset_mech(gss_mechanism *, gss_OID);
     85 
     86 #define	DEFAULT_MINOR_STAT	((OM_uint32) ~0)
     87 
     88 OM_uint32
     89 kgss_acquire_cred_wrapped(minor_status,
     90 			desired_name,
     91 			time_req,
     92 			desired_mechs,
     93 			cred_usage,
     94 			output_cred_handle,
     95 			actual_mechs,
     96 			time_rec,
     97 			uid,
     98 			gssd_cred_verifier)
     99 	OM_uint32 *minor_status;
    100 	const gss_name_t desired_name;
    101 	OM_uint32 time_req;
    102 	const gss_OID_set desired_mechs;
    103 	int cred_usage;
    104 	gssd_cred_id_t *output_cred_handle;
    105 	gss_OID_set *actual_mechs;
    106 	OM_uint32 *time_rec;
    107 	uid_t uid;
    108 	OM_uint32 *gssd_cred_verifier;
    109 {
    110 	CLIENT *clnt;
    111 
    112 	OM_uint32 	minor_status_temp;
    113 	gss_buffer_desc	external_name;
    114 	gss_OID		name_type;
    115 	enum clnt_stat	client_stat;
    116 	int		i;
    117 
    118 	gss_acquire_cred_arg arg;
    119 	gss_acquire_cred_res res;
    120 
    121 	/* get the client handle to GSSD */
    122 
    123 	if ((clnt = getgssd_handle()) == NULL) {
    124 		GSSLOG(1, "kgss_acquire_cred: can't connect to server on %s\n",
    125 			server);
    126 		return (GSS_S_FAILURE);
    127 	}
    128 
    129 	/* convert the desired name from internal to external format */
    130 
    131 	if (gss_display_name(&minor_status_temp, desired_name, &external_name,
    132 				&name_type) != GSS_S_COMPLETE) {
    133 
    134 		*minor_status = (OM_uint32) minor_status_temp;
    135 		killgssd_handle(clnt);
    136 		GSSLOG0(1, "kgss_acquire_cred: display name failed\n");
    137 		return ((OM_uint32) GSS_S_FAILURE);
    138 	}
    139 
    140 
    141 	/* copy the procedure arguments into the rpc arg parameter */
    142 
    143 	arg.uid = (OM_uint32) uid;
    144 
    145 	arg.desired_name.GSS_BUFFER_T_len = (uint_t)external_name.length;
    146 	arg.desired_name.GSS_BUFFER_T_val = (char *)external_name.value;
    147 
    148 	arg.name_type.GSS_OID_len =
    149 		name_type == GSS_C_NULL_OID ?
    150 			0 : (uint_t)name_type->length;
    151 
    152 	arg.name_type.GSS_OID_val =
    153 		name_type == GSS_C_NULL_OID ?
    154 			(char *)NULL : (char *)name_type->elements;
    155 
    156 	arg.time_req = time_req;
    157 
    158 	if (desired_mechs != GSS_C_NULL_OID_SET) {
    159 		arg.desired_mechs.GSS_OID_SET_len =
    160 			(uint_t)desired_mechs->count;
    161 		arg.desired_mechs.GSS_OID_SET_val = (GSS_OID *)
    162 			MALLOC(sizeof (GSS_OID) * desired_mechs->count);
    163 
    164 		for (i = 0; i < desired_mechs->count; i++) {
    165 		    arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_len =
    166 			(uint_t)desired_mechs->elements[i].length;
    167 		    arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val =
    168 			(char *)MALLOC(desired_mechs->elements[i].length);
    169 		    (void) memcpy(
    170 			arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val,
    171 			desired_mechs->elements[i].elements,
    172 			desired_mechs->elements[i].length);
    173 		}
    174 	} else
    175 		arg.desired_mechs.GSS_OID_SET_len = 0;
    176 
    177 	arg.cred_usage = cred_usage;
    178 
    179 	/* call the remote procedure */
    180 
    181 	bzero((caddr_t)&res, sizeof (res));
    182 	client_stat = gss_acquire_cred_1(&arg, &res, clnt);
    183 
    184 	(void) gss_release_buffer(&minor_status_temp, &external_name);
    185 	if (desired_mechs != GSS_C_NULL_OID_SET) {
    186 		for (i = 0; i < desired_mechs->count; i++)
    187 			FREE(arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val,
    188 			    arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_len);
    189 		FREE(arg.desired_mechs.GSS_OID_SET_val,
    190 		    arg.desired_mechs.GSS_OID_SET_len * sizeof (GSS_OID));
    191 	}
    192 
    193 	if (client_stat != RPC_SUCCESS) {
    194 
    195 		/*
    196 		 * if the RPC call times out, null out all return arguments,
    197 		 * set minor_status to its maximum value, and return
    198 		 * GSS_S_FAILURE
    199 		 */
    200 
    201 		if (minor_status != NULL)
    202 			*minor_status = DEFAULT_MINOR_STAT;
    203 		if (output_cred_handle != NULL)
    204 			*output_cred_handle = NULL;
    205 		if (actual_mechs != NULL)
    206 			*actual_mechs = NULL;
    207 		if (time_rec != NULL)
    208 			*time_rec = 0;
    209 
    210 		killgssd_handle(clnt);
    211 		GSSLOG0(1, "kgss_acquire_cred: RPC call times out\n");
    212 		return (GSS_S_FAILURE);
    213 	}
    214 
    215 	/* copy the rpc results into the return arguments */
    216 
    217 	if (minor_status != NULL)
    218 		*minor_status = res.minor_status;
    219 
    220 	if (output_cred_handle != NULL &&
    221 		(res.status == GSS_S_COMPLETE)) {
    222 	    *output_cred_handle =
    223 		*((gssd_cred_id_t *)res.output_cred_handle.GSS_CRED_ID_T_val);
    224 	    *gssd_cred_verifier = res.gssd_cred_verifier;
    225 	}
    226 
    227 	if (res.status == GSS_S_COMPLETE &&
    228 		res.actual_mechs.GSS_OID_SET_len != 0 &&
    229 		actual_mechs != NULL) {
    230 		*actual_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
    231 		(*actual_mechs)->count =
    232 					(int)res.actual_mechs.GSS_OID_SET_len;
    233 		(*actual_mechs)->elements = (gss_OID)
    234 			MALLOC(sizeof (gss_OID_desc) * (*actual_mechs)->count);
    235 
    236 		for (i = 0; i < (*actual_mechs)->count; i++) {
    237 		    (*actual_mechs)->elements[i].length = (OM_uint32)
    238 			res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_len;
    239 		    (*actual_mechs)->elements[i].elements =
    240 			(void *) MALLOC((*actual_mechs)->elements[i].length);
    241 		    (void) memcpy((*actual_mechs)->elements[i].elements,
    242 			res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_val,
    243 			(*actual_mechs)->elements[i].length);
    244 		}
    245 	} else {
    246 		if (res.status == GSS_S_COMPLETE &&
    247 			actual_mechs != NULL)
    248 			(*actual_mechs) = NULL;
    249 	}
    250 
    251 	if (time_rec != NULL)
    252 		*time_rec = res.time_rec;
    253 
    254 	/*
    255 	 * free the memory allocated for the results and return with the status
    256 	 * received in the rpc call
    257 	 */
    258 
    259 	clnt_freeres(clnt, xdr_gss_acquire_cred_res, (caddr_t)&res);
    260 	killgssd_handle(clnt);
    261 	return (res.status);
    262 
    263 }
    264 
    265 OM_uint32
    266 kgss_acquire_cred(minor_status,
    267 		desired_name,
    268 		time_req,
    269 		desired_mechs,
    270 		cred_usage,
    271 		output_cred_handle,
    272 		actual_mechs,
    273 		time_rec,
    274 		uid)
    275 	OM_uint32 *minor_status;
    276 	const gss_name_t desired_name;
    277 	OM_uint32 time_req;
    278 	const gss_OID_set desired_mechs;
    279 	int cred_usage;
    280 	gss_cred_id_t *output_cred_handle;
    281 	gss_OID_set *actual_mechs;
    282 	OM_uint32 *time_rec;
    283 	uid_t uid;
    284 {
    285 
    286 	OM_uint32	err;
    287 	struct kgss_cred *kcred;
    288 
    289 	kcred = KGSS_CRED_ALLOC();
    290 	*output_cred_handle = (gss_cred_id_t)kcred;
    291 	err = kgss_acquire_cred_wrapped(minor_status, desired_name, time_req,
    292 		desired_mechs, cred_usage, &kcred->gssd_cred, actual_mechs,
    293 		time_rec, uid, &kcred->gssd_cred_verifier);
    294 	if (GSS_ERROR(err)) {
    295 		KGSS_CRED_FREE(kcred);
    296 		*output_cred_handle = GSS_C_NO_CREDENTIAL;
    297 	}
    298 	return (err);
    299 }
    300 
    301 OM_uint32
    302 kgss_add_cred_wrapped(minor_status,
    303 			input_cred_handle,
    304 			gssd_cred_verifier,
    305 			desired_name,
    306 			desired_mech_type,
    307 			cred_usage,
    308 			initiator_time_req,
    309 			acceptor_time_req,
    310 			actual_mechs,
    311 			initiator_time_rec,
    312 			acceptor_time_rec,
    313 			uid)
    314 	OM_uint32 *minor_status;
    315 	gssd_cred_id_t input_cred_handle;
    316 	OM_uint32 gssd_cred_verifier;
    317 	gss_name_t desired_name;
    318 	gss_OID desired_mech_type;
    319 	int cred_usage;
    320 	int initiator_time_req;
    321 	int acceptor_time_req;
    322 	gss_OID_set *actual_mechs;
    323 	OM_uint32 *initiator_time_rec;
    324 	OM_uint32 *acceptor_time_rec;
    325 	uid_t uid;
    326 {
    327 	CLIENT *clnt;
    328 
    329 	OM_uint32 	minor_status_temp;
    330 	gss_buffer_desc	external_name;
    331 	gss_OID		name_type;
    332 	int		i;
    333 
    334 	gss_add_cred_arg arg;
    335 	gss_add_cred_res res;
    336 
    337 
    338 	/*
    339 	 * NULL the params here once
    340 	 * If there are errors then we won't
    341 	 * have to do it for every error
    342 	 * case
    343 	 */
    344 
    345 	if (minor_status != NULL)
    346 		*minor_status = DEFAULT_MINOR_STAT;
    347 	if (actual_mechs != NULL)
    348 		*actual_mechs = NULL;
    349 	if (initiator_time_rec != NULL)
    350 		*initiator_time_rec = 0;
    351 	if (acceptor_time_rec != NULL)
    352 			*acceptor_time_rec = 0;
    353 	/* get the client handle to GSSD */
    354 
    355 	if ((clnt = getgssd_handle()) == NULL) {
    356 		GSSLOG(1, "kgss_add_cred: can't connect to server on %s\n",
    357 			server);
    358 		return (GSS_S_FAILURE);
    359 	}
    360 
    361 
    362 	/* convert the desired name from internal to external format */
    363 
    364 	if (gss_display_name(&minor_status_temp, desired_name, &external_name,
    365 				&name_type) != GSS_S_COMPLETE) {
    366 
    367 		*minor_status = (OM_uint32) minor_status_temp;
    368 		killgssd_handle(clnt);
    369 		GSSLOG0(1, "kgss_acquire_cred: display name failed\n");
    370 		return ((OM_uint32) GSS_S_FAILURE);
    371 	}
    372 
    373 
    374 	/* copy the procedure arguments into the rpc arg parameter */
    375 
    376 	arg.uid = (OM_uint32)uid;
    377 	arg.input_cred_handle.GSS_CRED_ID_T_len =
    378 			input_cred_handle ==
    379 			(gssd_cred_id_t)GSS_C_NO_CREDENTIAL ?
    380 			0 : (uint_t)sizeof (gssd_cred_id_t);
    381 	arg.input_cred_handle.GSS_CRED_ID_T_val = (char *)&input_cred_handle;
    382 	arg.gssd_cred_verifier = gssd_cred_verifier;
    383 	arg.desired_name.GSS_BUFFER_T_len = (uint_t)external_name.length;
    384 	arg.desired_name.GSS_BUFFER_T_val = (char *)external_name.value;
    385 	arg.name_type.GSS_OID_len =
    386 		name_type == GSS_C_NULL_OID ?
    387 			0 : (uint_t)name_type->length;
    388 	arg.name_type.GSS_OID_val =
    389 		name_type == GSS_C_NULL_OID ?
    390 			(char *)NULL : (char *)name_type->elements;
    391 
    392 	arg.desired_mech_type.GSS_OID_len =
    393 		(uint_t)(desired_mech_type != GSS_C_NULL_OID ?
    394 		desired_mech_type->length : 0);
    395 	arg.desired_mech_type.GSS_OID_val =
    396 		(char *)(desired_mech_type != GSS_C_NULL_OID ?
    397 		desired_mech_type->elements : 0);
    398 	arg.cred_usage = cred_usage;
    399 	arg.initiator_time_req = initiator_time_req;
    400 	arg.acceptor_time_req = acceptor_time_req;
    401 
    402 	/* call the remote procedure */
    403 
    404 	bzero((caddr_t)&res, sizeof (res));
    405 	if (gss_add_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
    406 
    407 		/*
    408 		 * if the RPC call times out, null out all return arguments,
    409 		 * set minor_status to its maximum value, and return
    410 		 * GSS_S_FAILURE
    411 		 */
    412 
    413 		killgssd_handle(clnt);
    414 		(void) gss_release_buffer(&minor_status_temp, &external_name);
    415 		GSSLOG0(1, "kgss_add_cred: RPC call times out\n");
    416 		return (GSS_S_FAILURE);
    417 	}
    418 
    419 	/* free the allocated memory for the flattened name */
    420 
    421 	(void) gss_release_buffer(&minor_status_temp, &external_name);
    422 
    423 	/* copy the rpc results into the return arguments */
    424 
    425 	if (minor_status != NULL)
    426 		*minor_status = res.minor_status;
    427 
    428 	if (res.status == GSS_S_COMPLETE &&
    429 		res.actual_mechs.GSS_OID_SET_len != 0 &&
    430 		actual_mechs != NULL) {
    431 		*actual_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
    432 		(*actual_mechs)->count =
    433 					(int)res.actual_mechs.GSS_OID_SET_len;
    434 		(*actual_mechs)->elements = (gss_OID)
    435 			MALLOC(sizeof (gss_OID_desc) * (*actual_mechs)->count);
    436 
    437 		for (i = 0; i < (*actual_mechs)->count; i++) {
    438 		    (*actual_mechs)->elements[i].length = (OM_uint32)
    439 			res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_len;
    440 		    (*actual_mechs)->elements[i].elements =
    441 			(void *) MALLOC((*actual_mechs)->elements[i].length);
    442 		    (void) memcpy((*actual_mechs)->elements[i].elements,
    443 			res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_val,
    444 			(*actual_mechs)->elements[i].length);
    445 		}
    446 	} else {
    447 		if (res.status == GSS_S_COMPLETE && actual_mechs != NULL)
    448 			(*actual_mechs) = NULL;
    449 	}
    450 	if (initiator_time_rec != NULL)
    451 		*initiator_time_rec = res.acceptor_time_rec;
    452 	if (acceptor_time_rec != NULL)
    453 		*acceptor_time_rec = res.acceptor_time_rec;
    454 
    455 	/*
    456 	 * free the memory allocated for the results and return with the status
    457 	 * received in the rpc call
    458 	 */
    459 
    460 	clnt_freeres(clnt, xdr_gss_add_cred_res, (caddr_t)&res);
    461 	killgssd_handle(clnt);
    462 	return (res.status);
    463 
    464 }
    465 
    466 OM_uint32
    467 kgss_add_cred(minor_status,
    468 			input_cred_handle,
    469 			desired_name,
    470 			desired_mech_type,
    471 			cred_usage,
    472 			initiator_time_req,
    473 			acceptor_time_req,
    474 			actual_mechs,
    475 			initiator_time_rec,
    476 			acceptor_time_rec,
    477 			uid)
    478 	OM_uint32 *minor_status;
    479 	gss_cred_id_t input_cred_handle;
    480 	gss_name_t desired_name;
    481 	gss_OID desired_mech_type;
    482 	int cred_usage;
    483 	int initiator_time_req;
    484 	int acceptor_time_req;
    485 	gss_OID_set *actual_mechs;
    486 	OM_uint32 *initiator_time_rec;
    487 	OM_uint32 *acceptor_time_rec;
    488 	uid_t uid;
    489 {
    490 
    491 	OM_uint32	err;
    492 	OM_uint32 gssd_cred_verifier;
    493 	gssd_cred_id_t gssd_input_cred_handle;
    494 
    495 	if (input_cred_handle != GSS_C_NO_CREDENTIAL) {
    496 		gssd_cred_verifier = KCRED_TO_CREDV(input_cred_handle);
    497 		gssd_input_cred_handle = KCRED_TO_CRED(input_cred_handle);
    498 	} else
    499 		gssd_input_cred_handle = (gssd_cred_id_t)GSS_C_NO_CREDENTIAL;
    500 
    501 	err = kgss_add_cred_wrapped(minor_status, gssd_input_cred_handle,
    502 			gssd_cred_verifier, desired_name, desired_mech_type,
    503 			cred_usage, initiator_time_req, acceptor_time_req,
    504 			actual_mechs, initiator_time_rec,
    505 			acceptor_time_rec, uid);
    506 	return (err);
    507 }
    508 
    509 
    510 OM_uint32
    511 kgss_release_cred_wrapped(minor_status,
    512 			cred_handle,
    513 			uid,
    514 			gssd_cred_verifier)
    515     OM_uint32 *minor_status;
    516     gssd_cred_id_t *cred_handle;
    517     uid_t uid;
    518     OM_uint32  gssd_cred_verifier;
    519 {
    520 	CLIENT *clnt;
    521 
    522 	gss_release_cred_arg arg;
    523 	gss_release_cred_res res;
    524 
    525 
    526 	/* get the client handle to GSSD */
    527 
    528 	if ((clnt = getgssd_handle()) == NULL) {
    529 		GSSLOG(1, "kgss_release_cred: can't connect to server on %s\n",
    530 			server);
    531 		return (GSS_S_FAILURE);
    532 	}
    533 
    534 	/* copy the procedure arguments into the rpc arg parameter */
    535 
    536 	arg.uid = (OM_uint32)uid;
    537 	arg.gssd_cred_verifier = gssd_cred_verifier;
    538 
    539 	if (cred_handle != NULL) {
    540 		arg.cred_handle.GSS_CRED_ID_T_len =
    541 					(uint_t)sizeof (gssd_cred_id_t);
    542 		arg.cred_handle.GSS_CRED_ID_T_val = (char *)cred_handle;
    543 	} else
    544 		arg.cred_handle.GSS_CRED_ID_T_len = 0;
    545 
    546 	/* call the remote procedure */
    547 
    548 	bzero((caddr_t)&res, sizeof (res));
    549 	if (gss_release_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
    550 
    551 	/*
    552 	 * if the RPC call times out, null out all return arguments, set
    553 	 * minor_status to its maximum value, and return GSS_S_FAILURE
    554 	 */
    555 
    556 		if (minor_status != NULL)
    557 			*minor_status = DEFAULT_MINOR_STAT;
    558 		if (cred_handle != NULL)
    559 			*cred_handle = NULL;
    560 
    561 		killgssd_handle(clnt);
    562 		GSSLOG0(1, "kgss_release_cred: RPC call times out\n");
    563 		return (GSS_S_FAILURE);
    564 	}
    565 
    566 	/* if the release succeeded, null out the cred_handle */
    567 
    568 	if (res.status == GSS_S_COMPLETE && cred_handle != NULL)
    569 		*cred_handle = NULL;
    570 
    571 	/* copy the rpc results into the return arguments */
    572 
    573 	if (minor_status != NULL)
    574 		*minor_status = res.minor_status;
    575 
    576 	/* return with status returned in rpc call */
    577 
    578 	killgssd_handle(clnt);
    579 
    580 	return (res.status);
    581 
    582 }
    583 
    584 OM_uint32
    585 kgss_release_cred(minor_status,
    586 			cred_handle,
    587 			uid)
    588     OM_uint32 *minor_status;
    589     gss_cred_id_t *cred_handle;
    590     uid_t uid;
    591 
    592 {
    593 
    594 	OM_uint32	err;
    595 	struct kgss_cred *kcred;
    596 
    597 	if (*cred_handle == GSS_C_NO_CREDENTIAL)
    598 		return (GSS_S_COMPLETE);
    599 	else
    600 		kcred = KCRED_TO_KGSS_CRED(*cred_handle);
    601 
    602 	err = kgss_release_cred_wrapped(minor_status, &kcred->gssd_cred,
    603 		uid, kcred->gssd_cred_verifier);
    604 	KGSS_CRED_FREE(kcred);
    605 	*cred_handle = GSS_C_NO_CREDENTIAL;
    606 	return (err);
    607 }
    608 
    609 static OM_uint32
    610 kgss_init_sec_context_wrapped(
    611 	OM_uint32 *minor_status,
    612 	const gssd_cred_id_t claimant_cred_handle,
    613 	OM_uint32 gssd_cred_verifier,
    614 	gssd_ctx_id_t *context_handle,
    615 	OM_uint32 *gssd_context_verifier,
    616 	const gss_name_t target_name,
    617 	const gss_OID mech_type,
    618 	int req_flags,
    619 	OM_uint32 time_req,
    620 	const gss_channel_bindings_t input_chan_bindings,
    621 	const gss_buffer_t input_token,
    622 	gss_OID *actual_mech_type,
    623 	gss_buffer_t output_token,
    624 	int *ret_flags,
    625 	OM_uint32 *time_rec,
    626 	uid_t uid)
    627 {
    628 	CLIENT *clnt;
    629 
    630 	OM_uint32 	minor_status_temp;
    631 	gss_buffer_desc	external_name;
    632 	gss_OID		name_type;
    633 
    634 	gss_init_sec_context_arg arg;
    635 	gss_init_sec_context_res res;
    636 
    637 	/* get the client handle to GSSD */
    638 
    639 	if ((clnt = getgssd_handle()) == NULL) {
    640 		GSSLOG(1,
    641 		"kgss_init_sec_context: can't connect to server on %s\n",
    642 		server);
    643 		return (GSS_S_FAILURE);
    644 	}
    645 
    646 	/* convert the target name from internal to external format */
    647 
    648 	if (gss_display_name(&minor_status_temp, target_name,
    649 		&external_name, &name_type) != GSS_S_COMPLETE) {
    650 
    651 		*minor_status = (OM_uint32) minor_status_temp;
    652 		killgssd_handle(clnt);
    653 		GSSLOG0(1, "kgss_init_sec_context: can't display name\n");
    654 		return ((OM_uint32) GSS_S_FAILURE);
    655 	}
    656 
    657 
    658 	/* copy the procedure arguments into the rpc arg parameter */
    659 
    660 	arg.uid = (OM_uint32)uid;
    661 
    662 	arg.context_handle.GSS_CTX_ID_T_len =
    663 		*context_handle == (gssd_ctx_id_t)GSS_C_NO_CONTEXT ?
    664 			0 : (uint_t)sizeof (gssd_ctx_id_t);
    665 	arg.context_handle.GSS_CTX_ID_T_val =  (char *)context_handle;
    666 
    667 	arg.gssd_context_verifier =  *gssd_context_verifier;
    668 
    669 	arg.claimant_cred_handle.GSS_CRED_ID_T_len =
    670 		claimant_cred_handle == (gssd_cred_id_t)GSS_C_NO_CREDENTIAL ?
    671 			0 : (uint_t)sizeof (gssd_cred_id_t);
    672 	arg.claimant_cred_handle.GSS_CRED_ID_T_val =
    673 						(char *)&claimant_cred_handle;
    674 	arg.gssd_cred_verifier = gssd_cred_verifier;
    675 
    676 	arg.target_name.GSS_BUFFER_T_len = (uint_t)external_name.length;
    677 	arg.target_name.GSS_BUFFER_T_val = (char *)external_name.value;
    678 
    679 	arg.name_type.GSS_OID_len =
    680 		name_type == GSS_C_NULL_OID ?
    681 			0 : (uint_t)name_type->length;
    682 
    683 	arg.name_type.GSS_OID_val =
    684 		name_type == GSS_C_NULL_OID ?
    685 			(char *)NULL : (char *)name_type->elements;
    686 
    687 	arg.mech_type.GSS_OID_len = (uint_t)(mech_type != GSS_C_NULL_OID ?
    688 						mech_type->length : 0);
    689 	arg.mech_type.GSS_OID_val = (char *)(mech_type != GSS_C_NULL_OID ?
    690 						mech_type->elements : 0);
    691 
    692 	arg.req_flags = req_flags;
    693 
    694 	arg.time_req = time_req;
    695 
    696 	if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) {
    697 		arg.input_chan_bindings.present = YES;
    698 		arg.input_chan_bindings.initiator_addrtype =
    699 			input_chan_bindings->initiator_addrtype;
    700 		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len =
    701 			(uint_t)input_chan_bindings->initiator_address.length;
    702 		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val =
    703 			(void *)input_chan_bindings->initiator_address.value;
    704 		arg.input_chan_bindings.acceptor_addrtype =
    705 			input_chan_bindings->acceptor_addrtype;
    706 		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len =
    707 			(uint_t)input_chan_bindings->acceptor_address.length;
    708 		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val =
    709 			(void *)input_chan_bindings->acceptor_address.value;
    710 		arg.input_chan_bindings.application_data.GSS_BUFFER_T_len =
    711 			(uint_t)input_chan_bindings->application_data.length;
    712 		arg.input_chan_bindings.application_data.GSS_BUFFER_T_val =
    713 			(void *)input_chan_bindings->application_data.value;
    714 	} else {
    715 		arg.input_chan_bindings.present = NO;
    716 		arg.input_chan_bindings.initiator_addrtype = 0;
    717 		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = 0;
    718 		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = 0;
    719 		arg.input_chan_bindings.acceptor_addrtype = 0;
    720 		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = 0;
    721 		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = 0;
    722 		arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = 0;
    723 		arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = 0;
    724 	}
    725 
    726 	arg.input_token.GSS_BUFFER_T_len =
    727 		(uint_t)(input_token != GSS_C_NO_BUFFER ?
    728 		input_token->length : 0);
    729 	arg.input_token.GSS_BUFFER_T_val =
    730 		(char *)(input_token != GSS_C_NO_BUFFER ?
    731 		input_token->value : 0);
    732 
    733 	/* call the remote procedure */
    734 
    735 	bzero((caddr_t)&res, sizeof (res));
    736 	if (gss_init_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
    737 
    738 	/*
    739 	 * if the RPC call times out, null out all return arguments, set
    740 	 * minor_status to its maximum value, and return GSS_S_FAILURE
    741 	 */
    742 
    743 		if (minor_status != NULL)
    744 			*minor_status = DEFAULT_MINOR_STAT;
    745 		if (actual_mech_type != NULL)
    746 			*actual_mech_type = NULL;
    747 		if (output_token != NULL)
    748 			output_token->length = 0;
    749 		if (ret_flags != NULL)
    750 			*ret_flags = 0;
    751 		if (time_rec != NULL)
    752 			*time_rec = 0;
    753 
    754 		killgssd_handle(clnt);
    755 		(void) gss_release_buffer(&minor_status_temp, &external_name);
    756 		GSSLOG0(1, "kgss_init_sec_context: RPC call times out\n");
    757 		return (GSS_S_FAILURE);
    758 	}
    759 
    760 	/* free the allocated memory for the flattened name */
    761 
    762 	(void) gss_release_buffer(&minor_status_temp, &external_name);
    763 
    764 	if (minor_status != NULL)
    765 		*minor_status = res.minor_status;
    766 
    767 	if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) {
    768 		output_token->length =
    769 			(size_t)res.output_token.GSS_BUFFER_T_len;
    770 		output_token->value =
    771 			(void *)MALLOC(output_token->length);
    772 		(void) memcpy(output_token->value,
    773 			    res.output_token.GSS_BUFFER_T_val,
    774 			    output_token->length);
    775 	}
    776 
    777 	/* if the call was successful, copy out the results */
    778 	if (res.status == (OM_uint32) GSS_S_COMPLETE ||
    779 		res.status == (OM_uint32) GSS_S_CONTINUE_NEEDED) {
    780 		/*
    781 		 * if the return code is GSS_S_CONTINUE_NEEDED
    782 		 * ignore all return parameters except for
    783 		 * status codes, output token and context handle.
    784 		 */
    785 		*context_handle =
    786 			*((gssd_ctx_id_t *)
    787 			res.context_handle.GSS_CTX_ID_T_val);
    788 		*gssd_context_verifier = res.gssd_context_verifier;
    789 
    790 		if (res.status == GSS_S_COMPLETE) {
    791 			if (actual_mech_type != NULL) {
    792 				*actual_mech_type =
    793 					(gss_OID) MALLOC(sizeof (gss_OID_desc));
    794 				(*actual_mech_type)->length =
    795 					(OM_UINT32)
    796 					res.actual_mech_type.GSS_OID_len;
    797 				(*actual_mech_type)->elements =
    798 					(void *)
    799 					MALLOC((*actual_mech_type)->length);
    800 				(void) memcpy((*actual_mech_type)->elements,
    801 					(void *)
    802 					res.actual_mech_type.GSS_OID_val,
    803 					(*actual_mech_type)->length);
    804 			}
    805 
    806 
    807 			if (ret_flags != NULL)
    808 				*ret_flags = res.ret_flags;
    809 
    810 			if (time_rec != NULL)
    811 				*time_rec = res.time_rec;
    812 		}
    813 	}
    814 
    815 	/*
    816 	 * free the memory allocated for the results and return with the status
    817 	 * received in the rpc call
    818 	 */
    819 
    820 	clnt_freeres(clnt, xdr_gss_init_sec_context_res, (caddr_t)&res);
    821 	killgssd_handle(clnt);
    822 	return (res.status);
    823 
    824 }
    825 
    826 static struct gss_config default_gc = {
    827 	{ 0, NULL},
    828 	NULL,
    829 	NULL,
    830 	0,
    831 /* EXPORT DELETE START */ /* CRYPT DELETE START */
    832 	kgss_unseal_wrapped,
    833 /* EXPORT DELETE END */ /* CRYPT DELETE END */
    834 	NULL,		/* kgss_delete_sec_context_wrapped */
    835 /* EXPORT DELETE START */ /* CRYPT DELETE START */
    836 	kgss_seal_wrapped,
    837 /* EXPORT DELETE END */ /* CRYPT DELETE END */
    838 	NULL,		/* kgss_import_sec_context */
    839 /* EXPORT DELETE START */
    840 /* CRYPT DELETE START */
    841 #if 0
    842 /* CRYPT DELETE END */
    843 	kgss_seal_wrapped,
    844 	kgss_unseal_wrapped,
    845 /* CRYPT DELETE START */
    846 #endif
    847 /* CRYPT DELETE END */
    848 /* EXPORT DELETE END */
    849 	kgss_sign_wrapped,
    850 	kgss_verify_wrapped
    851 };
    852 
    853 void
    854 kgss_free_oid(gss_OID oid)
    855 {
    856 	FREE(oid->elements, oid->length);
    857 	FREE(oid, sizeof (gss_OID_desc));
    858 }
    859 
    860 OM_uint32
    861 kgss_init_sec_context(
    862 	OM_uint32 *minor_status,
    863 	const gss_cred_id_t claimant_cred_handle,
    864 	gss_ctx_id_t *context_handle,
    865 	const gss_name_t target_name,
    866 	const gss_OID mech_type,
    867 	int req_flags,
    868 	OM_uint32 time_req,
    869 	const gss_channel_bindings_t input_chan_bindings,
    870 	const gss_buffer_t input_token,
    871 	gss_OID *actual_mech_type,
    872 	gss_buffer_t output_token,
    873 	int *ret_flags,
    874 	OM_uint32 *time_rec,
    875 	uid_t uid)
    876 {
    877 	OM_uint32	err;
    878 	struct kgss_ctx	*kctx;
    879 	gss_OID	amt;
    880 	gssd_cred_id_t gssd_cl_cred_handle;
    881 	OM_uint32 gssd_cred_verifier;
    882 
    883 	/*
    884 	 * If this is an initial call, we'll need to create the
    885 	 * wrapper struct that contains kernel state information, and
    886 	 * a reference to the handle from gssd.
    887 	 */
    888 	if (*context_handle == GSS_C_NO_CONTEXT) {
    889 		kctx = KGSS_ALLOC();
    890 		/*
    891 		 * The default gss-mechanism struct as pointers to
    892 		 * the sign/seal/verify/unseal routines that make
    893 		 * upcalls to gssd.
    894 		 */
    895 		kctx->mech = &default_gc;
    896 		kctx->gssd_ctx = (gssd_ctx_id_t)GSS_C_NO_CONTEXT;
    897 		*context_handle = (gss_ctx_id_t)kctx;
    898 	} else
    899 		kctx = (struct kgss_ctx *)*context_handle;
    900 
    901 	if (claimant_cred_handle != GSS_C_NO_CREDENTIAL) {
    902 		gssd_cred_verifier = KCRED_TO_CREDV(claimant_cred_handle);
    903 		gssd_cl_cred_handle = KCRED_TO_CRED(claimant_cred_handle);
    904 	} else
    905 		gssd_cl_cred_handle = (gssd_cred_id_t)GSS_C_NO_CREDENTIAL;
    906 
    907 	/*
    908 	 * We need to know the resulting mechanism oid, so allocate
    909 	 * it if the caller won't.
    910 	 */
    911 	if (actual_mech_type == NULL)
    912 		actual_mech_type = &amt;
    913 
    914 	err = kgss_init_sec_context_wrapped(minor_status, gssd_cl_cred_handle,
    915 		gssd_cred_verifier, &kctx->gssd_ctx, &kctx->gssd_ctx_verifier,
    916 		target_name, mech_type, req_flags, time_req,
    917 		input_chan_bindings, input_token, actual_mech_type,
    918 		output_token, ret_flags, time_rec, uid);
    919 
    920 	if (GSS_ERROR(err)) {
    921 		KGSS_FREE(kctx);
    922 		*context_handle = GSS_C_NO_CONTEXT;
    923 	} else if (err == GSS_S_COMPLETE) {
    924 		/*
    925 		 * Now check if there is a kernel module for this
    926 		 * mechanism OID. If so, set the gss_mechanism structure
    927 		 * in the wrapper context to point to the kernel mech.
    928 		 */
    929 		__kgss_reset_mech(&kctx->mech, *actual_mech_type);
    930 
    931 		/*
    932 		 * If the mech oid was allocated for us, free it.
    933 		 */
    934 		if (&amt == actual_mech_type) {
    935 			kgss_free_oid(amt);
    936 		}
    937 	}
    938 	return (err);
    939 }
    940 
    941 static OM_uint32
    942 kgss_accept_sec_context_wrapped(
    943 	OM_uint32 *minor_status,
    944 	gssd_ctx_id_t *context_handle,
    945 	OM_uint32 *gssd_context_verifier,
    946 	const gssd_cred_id_t verifier_cred_handle,
    947 	OM_uint32 gssd_cred_verifier,
    948 	const gss_buffer_t input_token,
    949 	const gss_channel_bindings_t input_chan_bindings,
    950 	gss_buffer_t src_name,
    951 	gss_OID *mech_type,
    952 	gss_buffer_t output_token,
    953 	int *ret_flags,
    954 	OM_uint32 *time_rec,
    955 	gss_cred_id_t *delegated_cred_handle,
    956 	uid_t uid)
    957 {
    958 	CLIENT *clnt;
    959 
    960 	gss_accept_sec_context_arg arg;
    961 	gss_accept_sec_context_res res;
    962 	struct kgss_cred *kcred;
    963 
    964 	/* get the client handle to GSSD */
    965 
    966 	if ((clnt = getgssd_handle()) == NULL) {
    967 		GSSLOG(1,
    968 		"kgss_accept_sec_context: can't connect to server on %s\n",
    969 		server);
    970 		return (GSS_S_FAILURE);
    971 	}
    972 
    973 	/* copy the procedure arguments into the rpc arg parameter */
    974 
    975 	arg.uid = (OM_uint32)uid;
    976 
    977 	arg.context_handle.GSS_CTX_ID_T_len =
    978 		*context_handle == (gssd_ctx_id_t)GSS_C_NO_CONTEXT ?
    979 			0 : (uint_t)sizeof (gssd_ctx_id_t);
    980 	arg.context_handle.GSS_CTX_ID_T_val =  (char *)context_handle;
    981 	arg.gssd_context_verifier = *gssd_context_verifier;
    982 
    983 	arg.verifier_cred_handle.GSS_CRED_ID_T_len =
    984 			verifier_cred_handle ==
    985 			(gssd_cred_id_t)GSS_C_NO_CREDENTIAL ?
    986 			0 : (uint_t)sizeof (gssd_cred_id_t);
    987 	arg.verifier_cred_handle.GSS_CRED_ID_T_val =
    988 						(char *)&verifier_cred_handle;
    989 	arg.gssd_cred_verifier = gssd_cred_verifier;
    990 
    991 	arg.input_token_buffer.GSS_BUFFER_T_len =
    992 			(uint_t)(input_token != GSS_C_NO_BUFFER ?
    993 						input_token->length : 0);
    994 	arg.input_token_buffer.GSS_BUFFER_T_val =
    995 			(char *)(input_token != GSS_C_NO_BUFFER ?
    996 						input_token->value : 0);
    997 
    998 	if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) {
    999 		arg.input_chan_bindings.present = YES;
   1000 		arg.input_chan_bindings.initiator_addrtype =
   1001 			input_chan_bindings->initiator_addrtype;
   1002 		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len =
   1003 			(uint_t)input_chan_bindings->initiator_address.length;
   1004 		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val =
   1005 			(void *)input_chan_bindings->initiator_address.value;
   1006 		arg.input_chan_bindings.acceptor_addrtype =
   1007 			input_chan_bindings->acceptor_addrtype;
   1008 		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len =
   1009 			(uint_t)input_chan_bindings->acceptor_address.length;
   1010 		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val =
   1011 			(void *)input_chan_bindings->acceptor_address.value;
   1012 		arg.input_chan_bindings.application_data.GSS_BUFFER_T_len =
   1013 			(uint_t)input_chan_bindings->application_data.length;
   1014 		arg.input_chan_bindings.application_data.GSS_BUFFER_T_val =
   1015 			(void *)input_chan_bindings->application_data.value;
   1016 	} else {
   1017 
   1018 		arg.input_chan_bindings.present = NO;
   1019 		arg.input_chan_bindings.initiator_addrtype = 0;
   1020 		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = 0;
   1021 		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = 0;
   1022 		arg.input_chan_bindings.acceptor_addrtype = 0;
   1023 		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = 0;
   1024 		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = 0;
   1025 		arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = 0;
   1026 		arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = 0;
   1027 	}
   1028 
   1029 	/* set the return parameters in case of errors.... */
   1030 	if (minor_status != NULL)
   1031 		*minor_status = DEFAULT_MINOR_STAT;
   1032 	if (src_name != NULL) {
   1033 		src_name->length = 0;
   1034 		src_name->value = NULL;
   1035 	}
   1036 	if (mech_type != NULL)
   1037 		*mech_type = NULL;
   1038 	if (output_token != NULL)
   1039 		output_token->length = 0;
   1040 	if (ret_flags != NULL)
   1041 		*ret_flags = 0;
   1042 	if (time_rec != NULL)
   1043 		*time_rec = 0;
   1044 	if (delegated_cred_handle != NULL)
   1045 		*delegated_cred_handle = NULL;
   1046 
   1047 	/* call the remote procedure */
   1048 
   1049 	bzero((caddr_t)&res, sizeof (res));
   1050 	if (gss_accept_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
   1051 		killgssd_handle(clnt);
   1052 		GSSLOG0(1, "kgss_accept_sec_context: RPC call times out\n");
   1053 		return (GSS_S_FAILURE);
   1054 	}
   1055 
   1056 	if (minor_status != NULL)
   1057 		*minor_status = res.minor_status;
   1058 
   1059 	if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) {
   1060 		output_token->length =
   1061 			res.output_token.GSS_BUFFER_T_len;
   1062 		output_token->value =
   1063 			(void *)  MALLOC(output_token->length);
   1064 		(void) memcpy(output_token->value,
   1065 			    res.output_token.GSS_BUFFER_T_val,
   1066 			    output_token->length);
   1067 	}
   1068 
   1069 	/* if the call was successful, copy out the results */
   1070 
   1071 	if (res.status == (OM_uint32) GSS_S_COMPLETE ||
   1072 		res.status == (OM_uint32) GSS_S_CONTINUE_NEEDED) {
   1073 
   1074 		/*
   1075 		 * the only parameters that are ready when we
   1076 		 * get GSS_S_CONTINUE_NEEDED are: minor, ctxt_handle,
   1077 		 * and the output token to send to the peer.
   1078 		 */
   1079 
   1080 		*context_handle = *((gssd_ctx_id_t *)
   1081 			res.context_handle.GSS_CTX_ID_T_val);
   1082 			*gssd_context_verifier = res.gssd_context_verifier;
   1083 
   1084 		/* these other parameters are only ready upon GSS_S_COMPLETE */
   1085 		if (res.status == (OM_uint32) GSS_S_COMPLETE) {
   1086 
   1087 			if (src_name != NULL) {
   1088 			    src_name->length = res.src_name.GSS_BUFFER_T_len;
   1089 			    src_name->value = res.src_name.GSS_BUFFER_T_val;
   1090 			    res.src_name.GSS_BUFFER_T_val = NULL;
   1091 			    res.src_name.GSS_BUFFER_T_len = 0;
   1092 			}
   1093 
   1094 			/*
   1095 			 * move mech type returned to mech_type
   1096 			 * for gss_import_name_for_mech()
   1097 			 */
   1098 			if (mech_type != NULL) {
   1099 				*mech_type = (gss_OID)
   1100 					MALLOC(sizeof (gss_OID_desc));
   1101 				(*mech_type)->length =
   1102 					(OM_UINT32) res.mech_type.GSS_OID_len;
   1103 				(*mech_type)->elements =
   1104 					(void *) MALLOC((*mech_type)->length);
   1105 				(void) memcpy((*mech_type)->elements,
   1106 					res.mech_type.GSS_OID_val,
   1107 					(*mech_type)->length);
   1108 			}
   1109 
   1110 			if (ret_flags != NULL)
   1111 				*ret_flags = res.ret_flags;
   1112 
   1113 			if (time_rec != NULL)
   1114 				*time_rec = res.time_rec;
   1115 
   1116 			if ((delegated_cred_handle != NULL) &&
   1117 				(res.delegated_cred_handle.GSS_CRED_ID_T_len
   1118 				!= 0)) {
   1119 				kcred = KGSS_CRED_ALLOC();
   1120 				kcred->gssd_cred =
   1121 				*((gssd_cred_id_t *)
   1122 				res.delegated_cred_handle.GSS_CRED_ID_T_val);
   1123 				kcred->gssd_cred_verifier =
   1124 					res.gssd_context_verifier;
   1125 				*delegated_cred_handle = (gss_cred_id_t)kcred;
   1126 			}
   1127 
   1128 		}
   1129 	}
   1130 
   1131 
   1132 	/*
   1133 	 * free the memory allocated for the results and return with the status
   1134 	 * received in the rpc call
   1135 	 */
   1136 
   1137 	clnt_freeres(clnt, xdr_gss_accept_sec_context_res, (caddr_t)&res);
   1138 	killgssd_handle(clnt);
   1139 	return (res.status);
   1140 
   1141 }
   1142 
   1143 OM_uint32
   1144 kgss_accept_sec_context(
   1145 	OM_uint32 *minor_status,
   1146 	gss_ctx_id_t *context_handle,
   1147 	const gss_cred_id_t verifier_cred_handle,
   1148 	const gss_buffer_t input_token,
   1149 	const gss_channel_bindings_t input_chan_bindings,
   1150 	gss_buffer_t src_name,
   1151 	gss_OID *mech_type,
   1152 	gss_buffer_t output_token,
   1153 	int *ret_flags,
   1154 	OM_uint32 *time_rec,
   1155 	gss_cred_id_t *delegated_cred_handle,
   1156 	uid_t uid)
   1157 {
   1158 	OM_uint32 err;
   1159 	struct kgss_ctx	*kctx;
   1160 	gss_OID mt;
   1161 	OM_uint32 gssd_cred_verifier;
   1162 	gssd_cred_id_t gssd_ver_cred_handle;
   1163 
   1164 
   1165 	/*
   1166 	 * See kgss_init_sec_context() to get an idea of what is going
   1167 	 * on here.
   1168 	 */
   1169 	if (mech_type == NULL)
   1170 		mech_type = &mt;
   1171 
   1172 	if (*context_handle == GSS_C_NO_CONTEXT) {
   1173 		kctx = KGSS_ALLOC();
   1174 		kctx->mech = &default_gc;
   1175 		kctx->gssd_ctx = (gssd_ctx_id_t)GSS_C_NO_CONTEXT;
   1176 		*context_handle = (gss_ctx_id_t)kctx;
   1177 	} else
   1178 		kctx = (struct kgss_ctx *)*context_handle;
   1179 
   1180 	if (verifier_cred_handle != GSS_C_NO_CREDENTIAL) {
   1181 		gssd_cred_verifier = KCRED_TO_CREDV(verifier_cred_handle);
   1182 		gssd_ver_cred_handle = KCRED_TO_CRED(verifier_cred_handle);
   1183 	} else
   1184 		gssd_ver_cred_handle = (gssd_cred_id_t)GSS_C_NO_CREDENTIAL;
   1185 
   1186 	err = kgss_accept_sec_context_wrapped(minor_status,
   1187 		&kctx->gssd_ctx, &kctx->gssd_ctx_verifier,
   1188 		gssd_ver_cred_handle, gssd_cred_verifier,
   1189 		input_token, input_chan_bindings, src_name,
   1190 		mech_type, output_token, ret_flags,
   1191 		time_rec, delegated_cred_handle, uid);
   1192 
   1193 	if (GSS_ERROR(err)) {
   1194 		KGSS_FREE(kctx);
   1195 		*context_handle = GSS_C_NO_CONTEXT;
   1196 
   1197 	} else if (err == GSS_S_COMPLETE) {
   1198 		__kgss_reset_mech(&kctx->mech, *mech_type);
   1199 
   1200 		/*
   1201 		 * If the mech oid was allocated for us, free it.
   1202 		 */
   1203 		if (&mt == mech_type) {
   1204 			kgss_free_oid(mt);
   1205 		}
   1206 	}
   1207 
   1208 	return (err);
   1209 }
   1210 
   1211 OM_uint32
   1212 kgss_process_context_token(minor_status,
   1213 				context_handle,
   1214 				token_buffer,
   1215 				uid)
   1216 	OM_uint32 *minor_status;
   1217 	const gss_ctx_id_t context_handle;
   1218 	gss_buffer_t token_buffer;
   1219 	uid_t uid;
   1220 {
   1221 	CLIENT *clnt;
   1222 	OM_uint32 gssd_context_verifier;
   1223 	gssd_ctx_id_t gssd_ctx_handle;
   1224 	gss_process_context_token_arg arg;
   1225 	gss_process_context_token_res res;
   1226 
   1227 	gssd_context_verifier = KGSS_CTX_TO_GSSD_CTXV(context_handle);
   1228 	gssd_ctx_handle = (gssd_ctx_id_t)KGSS_CTX_TO_GSSD_CTX(context_handle);
   1229 
   1230 	/* get the client handle to GSSD */
   1231 
   1232 	if ((clnt = getgssd_handle()) == NULL) {
   1233 		GSSLOG(1,
   1234 		"kgss_process_context_token: can't connect to server on %s\n",
   1235 		server);
   1236 		return (GSS_S_FAILURE);
   1237 	}
   1238 
   1239 	/* copy the procedure arguments into the rpc arg parameter */
   1240 
   1241 	arg.uid = (OM_uint32) uid;
   1242 
   1243 	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
   1244 	arg.context_handle.GSS_CTX_ID_T_val = (char *)&gssd_ctx_handle;
   1245 	arg.gssd_context_verifier = gssd_context_verifier;
   1246 	arg.token_buffer.GSS_BUFFER_T_len = (uint_t)token_buffer->length;
   1247 	arg.token_buffer.GSS_BUFFER_T_val = (char *)token_buffer->value;
   1248 
   1249 	/* call the remote procedure */
   1250 
   1251 	bzero(&res, sizeof (res));
   1252 
   1253 	if (gss_process_context_token_1(&arg, &res, clnt) != RPC_SUCCESS) {
   1254 
   1255 	/*
   1256 	 * if the RPC call times out, null out all return arguments, set
   1257 	 * minor_status to its maximum value, and return GSS_S_FAILURE
   1258 	 */
   1259 
   1260 		if (minor_status != NULL)
   1261 			*minor_status = DEFAULT_MINOR_STAT;
   1262 		GSSLOG0(1, "kgss_process_context_token: RPC call times out\n");
   1263 		killgssd_handle(clnt);
   1264 		return (GSS_S_FAILURE);
   1265 	}
   1266 
   1267 	/* copy the rpc results into the return arguments */
   1268 
   1269 	if (minor_status != NULL)
   1270 		*minor_status = res.minor_status;
   1271 
   1272 	/* return with status returned in rpc call */
   1273 
   1274 	killgssd_handle(clnt);
   1275 	return (res.status);
   1276 
   1277 }
   1278 
   1279 /*ARGSUSED*/
   1280 static OM_uint32
   1281 kgss_delete_sec_context_wrapped(void *private,
   1282 			OM_uint32 *minor_status,
   1283 			gssd_ctx_id_t *context_handle,
   1284 			gss_buffer_t output_token,
   1285 			OM_uint32 gssd_context_verifier)
   1286 
   1287 
   1288 {
   1289 	CLIENT *clnt;
   1290 
   1291 	gss_delete_sec_context_arg arg;
   1292 	gss_delete_sec_context_res res;
   1293 
   1294 
   1295 	/* get the client handle to GSSD */
   1296 
   1297 	if ((clnt = getgssd_handle()) == NULL) {
   1298 		GSSLOG(1,
   1299 		"kgss_delete_sec_context: can't connect to server on %s\n",
   1300 		server);
   1301 		return (GSS_S_FAILURE);
   1302 	}
   1303 
   1304 	/* copy the procedure arguments into the rpc arg parameter */
   1305 
   1306 	arg.context_handle.GSS_CTX_ID_T_len =
   1307 		*context_handle == (gssd_ctx_id_t)GSS_C_NO_CONTEXT ?
   1308 			0 : (uint_t)sizeof (gssd_ctx_id_t);
   1309 	arg.context_handle.GSS_CTX_ID_T_val =  (char *)context_handle;
   1310 
   1311 	arg.gssd_context_verifier = gssd_context_verifier;
   1312 
   1313 	/* call the remote procedure */
   1314 
   1315 	bzero((caddr_t)&res, sizeof (res));
   1316 	if (gss_delete_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
   1317 
   1318 	/*
   1319 	 * if the RPC call times out, null out all return arguments, set
   1320 	 * minor_status to its maximum value, and return GSS_S_FAILURE
   1321 	 */
   1322 
   1323 		if (minor_status != NULL)
   1324 			*minor_status = DEFAULT_MINOR_STAT;
   1325 		if (context_handle != NULL)
   1326 			*context_handle = NULL;
   1327 		if (output_token != NULL)
   1328 			output_token->length = 0;
   1329 
   1330 		killgssd_handle(clnt);
   1331 		GSSLOG0(1, "kgssd_delete_sec_context: RPC call times out\n");
   1332 		return (GSS_S_FAILURE);
   1333 	}
   1334 
   1335 	/* copy the rpc results into the return arguments */
   1336 
   1337 	if (minor_status != NULL)
   1338 		*minor_status = res.minor_status;
   1339 
   1340 	if (res.context_handle.GSS_CTX_ID_T_len == 0)
   1341 		*context_handle = NULL;
   1342 	else
   1343 		*context_handle =
   1344 		    *((gssd_ctx_id_t *)res.context_handle.GSS_CTX_ID_T_val);
   1345 
   1346 	if (output_token != NULL) {
   1347 		output_token->length = res.output_token.GSS_BUFFER_T_len;
   1348 		output_token->value = res.output_token.GSS_BUFFER_T_val;
   1349 		res.output_token.GSS_BUFFER_T_len = 0;
   1350 		res.output_token.GSS_BUFFER_T_val = NULL;
   1351 	}
   1352 
   1353 	/*
   1354 	 * free the memory allocated for the results and return with the status
   1355 	 * received in the rpc call
   1356 	 */
   1357 
   1358 	clnt_freeres(clnt, xdr_gss_delete_sec_context_res, (caddr_t)&res);
   1359 	killgssd_handle(clnt);
   1360 	return (res.status);
   1361 
   1362 }
   1363 
   1364 OM_uint32
   1365 kgss_delete_sec_context(
   1366 		OM_uint32 *minor_status,
   1367 		gss_ctx_id_t *context_handle,
   1368 		gss_buffer_t output_token)
   1369 {
   1370 	OM_uint32 err;
   1371 	struct kgss_ctx	*kctx;
   1372 
   1373 	if (*context_handle == GSS_C_NO_CONTEXT) {
   1374 		GSSLOG0(8, "kgss_delete_sec_context: Null context handle \n");
   1375 		return (GSS_S_COMPLETE);
   1376 	} else
   1377 		kctx = (struct kgss_ctx *)*context_handle;
   1378 
   1379 	if (kctx->ctx_imported == FALSE) {
   1380 		if (kctx->gssd_ctx == (gssd_ctx_id_t)GSS_C_NO_CONTEXT) {
   1381 			KGSS_FREE(kctx);
   1382 			*context_handle = GSS_C_NO_CONTEXT;
   1383 			return (GSS_S_COMPLETE);
   1384 		}
   1385 		err = kgss_delete_sec_context_wrapped(
   1386 				KCTX_TO_PRIVATE(*context_handle),
   1387 				minor_status,
   1388 				&kctx->gssd_ctx,
   1389 				output_token,
   1390 				kctx->gssd_ctx_verifier);
   1391 	} else {
   1392 		if (kctx->gssd_i_ctx == (gss_ctx_id_t)GSS_C_NO_CONTEXT) {
   1393 			KGSS_FREE(kctx);
   1394 			*context_handle = GSS_C_NO_CONTEXT;
   1395 			return (GSS_S_COMPLETE);
   1396 		}
   1397 		err = KGSS_DELETE_SEC_CONTEXT(minor_status, kctx,
   1398 				&kctx->gssd_i_ctx,  output_token);
   1399 	}
   1400 	KGSS_FREE(kctx);
   1401 	*context_handle = GSS_C_NO_CONTEXT;
   1402 	return (err);
   1403 
   1404 }
   1405 
   1406 
   1407 OM_uint32
   1408 kgss_export_sec_context_wrapped(minor_status,
   1409 				context_handle,
   1410 				output_token,
   1411 				gssd_context_verifier)
   1412 	OM_uint32 *minor_status;
   1413 	gssd_ctx_id_t *context_handle;
   1414 	gss_buffer_t output_token;
   1415 	OM_uint32 gssd_context_verifier;
   1416 {
   1417 	CLIENT *clnt;
   1418 	gss_export_sec_context_arg arg;
   1419 	gss_export_sec_context_res res;
   1420 
   1421 
   1422 	/* get the client handle to GSSD */
   1423 
   1424 	if ((clnt = getgssd_handle()) == NULL) {
   1425 		GSSLOG(1, "kgss_export_sec_context_wrapped :"
   1426 			" can't connect to server on %s\n", server);
   1427 		return (GSS_S_FAILURE);
   1428 	}
   1429 
   1430 	/* copy the procedure arguments into the rpc arg parameter */
   1431 
   1432 	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
   1433 	arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle;
   1434 	arg.gssd_context_verifier = gssd_context_verifier;
   1435 
   1436 	/* call the remote procedure */
   1437 
   1438 	(void) memset(&res, 0, sizeof (res));
   1439 	if (gss_export_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
   1440 
   1441 	/*
   1442 	 * if the RPC call times out, null out all return arguments,
   1443 	 * set minor_status to its maximum value, and return
   1444 	 * GSS_S_FAILURE
   1445 	 */
   1446 
   1447 		if (minor_status != NULL)
   1448 			*minor_status = DEFAULT_MINOR_STAT;
   1449 		if (context_handle != NULL)
   1450 			*context_handle = NULL;
   1451 		if (output_token != NULL)
   1452 			output_token->length = 0;
   1453 		killgssd_handle(clnt);
   1454 		GSSLOG0(1,
   1455 		"kgss_export_sec_context_wrapped: RPC call times out\n");
   1456 		return (GSS_S_FAILURE);
   1457 	}
   1458 
   1459 	/* copy the rpc results into the return arguments */
   1460 
   1461 	if (minor_status != NULL)
   1462 		*minor_status = res.minor_status;
   1463 
   1464 	if (res.context_handle.GSS_CTX_ID_T_len == 0)
   1465 		*context_handle = NULL;
   1466 	else
   1467 		*context_handle =
   1468 		    *((gssd_ctx_id_t *)res.context_handle.GSS_CTX_ID_T_val);
   1469 
   1470 	if (output_token != NULL) {
   1471 		output_token->length = res.output_token.GSS_BUFFER_T_len;
   1472 		output_token->value =
   1473 			(void *)  MALLOC(output_token->length);
   1474 		(void) memcpy(output_token->value,
   1475 			res.output_token.GSS_BUFFER_T_val,
   1476 			output_token->length);
   1477 	}
   1478 
   1479 	/*
   1480 	 * free the memory allocated for the results and return with the status
   1481 	 * received in the rpc call
   1482 	 */
   1483 
   1484 	clnt_freeres(clnt, xdr_gss_export_sec_context_res, (caddr_t)&res);
   1485 	killgssd_handle(clnt);
   1486 	return (res.status);
   1487 
   1488 }
   1489 
   1490 OM_uint32
   1491 kgss_export_sec_context(minor_status,
   1492 			context_handle,
   1493 			output_token)
   1494 	OM_uint32 *minor_status;
   1495 	gss_ctx_id_t context_handle;
   1496 	gss_buffer_t output_token;
   1497 {
   1498 	struct kgss_ctx	*kctx;
   1499 
   1500 	if (context_handle == GSS_C_NO_CONTEXT)
   1501 		return (GSS_S_FAILURE);
   1502 	else
   1503 		kctx = (struct kgss_ctx *)context_handle;
   1504 
   1505 
   1506 
   1507 	/*
   1508 	 *  If there is a kernel module then import_sec context must be
   1509 	 *  supported and we make an upcall to export_sec_context.
   1510 	 *  If there is no kernel module then we return an error
   1511 	 */
   1512 
   1513 	*minor_status = 0;
   1514 
   1515 	if (kctx->mech->gss_import_sec_context) {
   1516 		GSSLOG0(8, "kgss_export_sec_context: Kernel mod available \n");
   1517 		return (kgss_export_sec_context_wrapped(minor_status,
   1518 						&kctx->gssd_ctx,
   1519 						output_token,
   1520 						kctx->gssd_ctx_verifier));
   1521 
   1522 	} else {
   1523 
   1524 		/*
   1525 		 * This is not the right error value; instead of
   1526 		 * inventing  new error we return GSS_S_NAME_NOT_MN
   1527 		 * This error is not returned by the export routine
   1528 		 */
   1529 
   1530 		GSSLOG0(8, "kgss_export_sec_context: Kernel mod "
   1531 			"unavailable \n");
   1532 		return (GSS_S_NAME_NOT_MN);
   1533 	}
   1534 
   1535 }
   1536 
   1537 OM_uint32
   1538 kgss_import_sec_context(minor_status,
   1539 			interprocess_token,
   1540 			context_handle)
   1541 
   1542 OM_uint32 *		minor_status;
   1543 const gss_buffer_t	interprocess_token;
   1544 gss_ctx_id_t 		context_handle;
   1545 
   1546 {
   1547 OM_uint32 status;
   1548 struct kgss_ctx	*kctx;
   1549 
   1550 size_t		length;
   1551 char		*p;
   1552 gss_buffer_desc token;
   1553 gss_ctx_id_t	internal_ctx_id;
   1554 	kctx = (struct kgss_ctx *)context_handle;
   1555 
   1556 	if (kctx->gssd_ctx != (gssd_ctx_id_t)GSS_C_NO_CONTEXT) {
   1557 		return (GSS_S_FAILURE);
   1558 	}
   1559 
   1560 	if (!(KCTX_TO_MECH(context_handle)->gss_import_sec_context)) {
   1561 
   1562 	/*
   1563 	 *  This should never happen
   1564 	 *  If Kernel import sec context does not exist the export
   1565 	 *  sec context should have caught this and returned an error
   1566 	 *  and the caller should not have called this routine
   1567 	 */
   1568 		GSSLOG0(1, "import_sec_context  called improperly\n");
   1569 		return (GSS_S_FAILURE);
   1570 	}
   1571 	*minor_status = 0;
   1572 
   1573 	if (interprocess_token->length == 0 || interprocess_token->value == 0)
   1574 		return (GSS_S_DEFECTIVE_TOKEN);
   1575 
   1576 	status = GSS_S_FAILURE;
   1577 
   1578 	p = interprocess_token->value;
   1579 	length = *p++;
   1580 	length = (length << 8) + *p++;
   1581 	length = (length << 8) + *p++;
   1582 	length = (length << 8) + *p++;
   1583 
   1584 	p += length;
   1585 
   1586 	token.length = interprocess_token->length - 4 - length;
   1587 	token.value = p;
   1588 
   1589 	/*
   1590 	 * select the approprate underlying mechanism routine and
   1591 	 * call it.
   1592 	 */
   1593 
   1594 	status = KGSS_IMPORT_SEC_CONTEXT(minor_status, &token, kctx,
   1595 				&internal_ctx_id);
   1596 
   1597 	if (status == GSS_S_COMPLETE) {
   1598 		KCTX_TO_I_CTX(kctx) = internal_ctx_id;
   1599 		kctx->ctx_imported = TRUE;
   1600 		return (GSS_S_COMPLETE);
   1601 	} else
   1602 		return (status);
   1603 }
   1604 
   1605 /*ARGSUSED*/
   1606 OM_uint32
   1607 kgss_context_time(minor_status,
   1608 		context_handle,
   1609 		time_rec,
   1610 		uid)
   1611 	OM_uint32 *minor_status;
   1612 	const gss_ctx_id_t context_handle;
   1613 	OM_uint32 *time_rec;
   1614 	uid_t uid;
   1615 {
   1616 	return (GSS_S_FAILURE);
   1617 }
   1618 
   1619 /*ARGSUSED*/
   1620 static OM_uint32
   1621 kgss_sign_wrapped(void *private,
   1622 	OM_uint32 *minor_status,
   1623 	const gss_ctx_id_t ctx_handle,
   1624 	int qop_req,
   1625 	const gss_buffer_t message_buffer,
   1626 	gss_buffer_t msg_token,
   1627 	OM_uint32 gssd_context_verifier)
   1628 {
   1629 	CLIENT *clnt;
   1630 	gssd_ctx_id_t context_handle;
   1631 
   1632 	gss_sign_arg arg;
   1633 	gss_sign_res res;
   1634 	context_handle = (gssd_ctx_id_t)KCTX_TO_GSSD_CTX(ctx_handle);
   1635 	/* get the client handle to GSSD */
   1636 
   1637 	if ((clnt = getgssd_handle()) == NULL) {
   1638 		GSSLOG(1, "kgss_sign: can't connect to server on %s\n", server);
   1639 		return (GSS_S_FAILURE);
   1640 	}
   1641 
   1642 	/* copy the procedure arguments into the rpc arg parameter */
   1643 
   1644 	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
   1645 	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
   1646 
   1647 	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
   1648 	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
   1649 	arg.gssd_context_verifier = gssd_context_verifier;
   1650 
   1651 	arg.qop_req = qop_req;
   1652 
   1653 	arg.message_buffer.GSS_BUFFER_T_len = (uint_t)message_buffer->length;
   1654 	arg.message_buffer.GSS_BUFFER_T_val = (char *)message_buffer->value;
   1655 
   1656 	/* call the remote procedure */
   1657 
   1658 	bzero((caddr_t)&res, sizeof (res));
   1659 	if (gss_sign_1(&arg, &res, clnt) != RPC_SUCCESS) {
   1660 
   1661 	/*
   1662 	 * if the RPC call times out, null out all return arguments, set
   1663 	 * minor_status to its maximum value, and return GSS_S_FAILURE
   1664 	 */
   1665 
   1666 		if (minor_status != NULL)
   1667 			*minor_status = DEFAULT_MINOR_STAT;
   1668 		if (msg_token != NULL)
   1669 			msg_token->length = 0;
   1670 
   1671 		killgssd_handle(clnt);
   1672 		GSSLOG0(1, "kgss_sign: RPC call times out\n");
   1673 		return (GSS_S_FAILURE);
   1674 	}
   1675 
   1676 	/* copy the rpc results into the return arguments */
   1677 
   1678 	if (minor_status != NULL)
   1679 		*minor_status = res.minor_status;
   1680 
   1681 	if (msg_token != NULL) {
   1682 		msg_token->length = res.msg_token.GSS_BUFFER_T_len;
   1683 		msg_token->value = (void *) MALLOC(msg_token->length);
   1684 		(void) memcpy(msg_token->value, res.msg_token.GSS_BUFFER_T_val,
   1685 			msg_token->length);
   1686 	}
   1687 
   1688 	/*
   1689 	 * free the memory allocated for the results and return with the status
   1690 	 * received in the rpc call
   1691 	 */
   1692 
   1693 	clnt_freeres(clnt, xdr_gss_sign_res, (caddr_t)&res);
   1694 	killgssd_handle(clnt);
   1695 	return (res.status);
   1696 
   1697 }
   1698 
   1699 OM_uint32
   1700 kgss_sign(
   1701 	OM_uint32 *minor_status,
   1702 	const gss_ctx_id_t context_handle,
   1703 	int qop_req,
   1704 	const gss_buffer_t message_buffer,
   1705 	gss_buffer_t msg_token)
   1706 {
   1707 	if (context_handle == GSS_C_NO_CONTEXT)
   1708 		return (GSS_S_FAILURE);
   1709 	return (KGSS_SIGN(minor_status, context_handle, qop_req,
   1710 			message_buffer, msg_token));
   1711 }
   1712 
   1713 /*ARGSUSED*/
   1714 static OM_uint32
   1715 kgss_verify_wrapped(void *private,
   1716 	OM_uint32 *minor_status,
   1717 	const gss_ctx_id_t ctx_handle,
   1718 	const gss_buffer_t message_buffer,
   1719 	const gss_buffer_t token_buffer,
   1720 	int *qop_state,
   1721 	OM_uint32 gssd_context_verifier)
   1722 {
   1723 	CLIENT *clnt;
   1724 
   1725 	gssd_ctx_id_t context_handle;
   1726 	gss_verify_arg arg;
   1727 	gss_verify_res res;
   1728 
   1729 	context_handle = (gssd_ctx_id_t)KCTX_TO_GSSD_CTX(ctx_handle);
   1730 
   1731 	/* get the client handle to GSSD */
   1732 
   1733 	if ((clnt = getgssd_handle()) == NULL) {
   1734 		GSSLOG(1, "kgss_verify: can't connect to server on %s\n",
   1735 			server);
   1736 		return (GSS_S_FAILURE);
   1737 	}
   1738 
   1739 	/* copy the procedure arguments into the rpc arg parameter */
   1740 
   1741 	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gss_ctx_id_t);
   1742 	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
   1743 
   1744 	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
   1745 	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
   1746 	arg.gssd_context_verifier = gssd_context_verifier;
   1747 
   1748 	arg.message_buffer.GSS_BUFFER_T_len = (uint_t)message_buffer->length;
   1749 	arg.message_buffer.GSS_BUFFER_T_val = (char *)message_buffer->value;
   1750 
   1751 	arg.token_buffer.GSS_BUFFER_T_len = (uint_t)token_buffer->length;
   1752 	arg.token_buffer.GSS_BUFFER_T_val = (char *)token_buffer->value;
   1753 
   1754 	/* call the remote procedure */
   1755 
   1756 	bzero((caddr_t)&res, sizeof (res));
   1757 	if (gss_verify_1(&arg, &res, clnt) != RPC_SUCCESS) {
   1758 
   1759 	/*
   1760 	 * if the RPC call times out, null out all return arguments, set
   1761 	 * minor_status to its maximum value, and return GSS_S_FAILURE
   1762 	 */
   1763 
   1764 		if (minor_status != NULL)
   1765 			*minor_status = DEFAULT_MINOR_STAT;
   1766 		if (qop_state != NULL)
   1767 			*qop_state = 0;
   1768 
   1769 		killgssd_handle(clnt);
   1770 		GSSLOG0(1, "kgss_verify: RPC call times out\n");
   1771 		return (GSS_S_FAILURE);
   1772 	}
   1773 
   1774 	/* copy the rpc results into the return arguments */
   1775 
   1776 	if (minor_status != NULL)
   1777 		*minor_status = res.minor_status;
   1778 
   1779 	if (qop_state != NULL)
   1780 		*qop_state = res.qop_state;
   1781 
   1782 	/* return with status returned in rpc call */
   1783 
   1784 	killgssd_handle(clnt);
   1785 	return (res.status);
   1786 
   1787 }
   1788 
   1789 OM_uint32
   1790 kgss_verify(OM_uint32 *minor_status,
   1791 		const gss_ctx_id_t context_handle,
   1792 		const gss_buffer_t message_buffer,
   1793 		const gss_buffer_t token_buffer,
   1794 		int *qop_state)
   1795 {
   1796 	if (context_handle == GSS_C_NO_CONTEXT)
   1797 		return (GSS_S_FAILURE);
   1798 	return (KGSS_VERIFY(minor_status, context_handle,
   1799 			    message_buffer,
   1800 			    token_buffer,
   1801 			    qop_state));
   1802 }
   1803 
   1804 /* EXPORT DELETE START */
   1805 
   1806 /*ARGSUSED*/
   1807 static OM_uint32
   1808 kgss_seal_wrapped(void *private,
   1809 	OM_uint32 *minor_status,
   1810 	const gss_ctx_id_t ctx_handle,
   1811 	int conf_req_flag,
   1812 	int qop_req,
   1813 	const gss_buffer_t input_message_buffer,
   1814 	int *conf_state,
   1815 	gss_buffer_t output_message_buffer,
   1816 	OM_uint32 gssd_context_verifier)
   1817 {
   1818 	CLIENT *clnt;
   1819 	gssd_ctx_id_t	context_handle;
   1820 
   1821 	gss_seal_arg arg;
   1822 	gss_seal_res res;
   1823 
   1824 	context_handle = (gssd_ctx_id_t)KCTX_TO_GSSD_CTX(ctx_handle);
   1825 
   1826 	/* get the client handle to GSSD */
   1827 
   1828 	if ((clnt = getgssd_handle()) == NULL) {
   1829 		GSSLOG(1, "kgss_seal: can't connect to server on %s\n", server);
   1830 		return (GSS_S_FAILURE);
   1831 	}
   1832 
   1833 	/* copy the procedure arguments into the rpc arg parameter */
   1834 
   1835 	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gss_ctx_id_t);
   1836 	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
   1837 
   1838 	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (OM_uint32);
   1839 	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
   1840 	arg.gssd_context_verifier = gssd_context_verifier;
   1841 
   1842 	arg.conf_req_flag = conf_req_flag;
   1843 
   1844 	arg.qop_req = qop_req;
   1845 
   1846 	arg.input_message_buffer.GSS_BUFFER_T_len =
   1847 					(uint_t)input_message_buffer->length;
   1848 
   1849 	arg.input_message_buffer.GSS_BUFFER_T_val =
   1850 					(char *)input_message_buffer->value;
   1851 
   1852 	/* call the remote procedure */
   1853 
   1854 	bzero((caddr_t)&res, sizeof (res));
   1855 	if (gss_seal_1(&arg, &res, clnt) != RPC_SUCCESS) {
   1856 
   1857 	/*
   1858 	 * if the RPC call times out, null out all return arguments, set
   1859 	 * minor_status to its maximum value, and return GSS_S_FAILURE
   1860 	 */
   1861 
   1862 		if (minor_status != NULL)
   1863 			*minor_status = DEFAULT_MINOR_STAT;
   1864 		if (conf_state != NULL)
   1865 			*conf_state = 0;
   1866 		if (output_message_buffer != NULL)
   1867 			output_message_buffer->length = 0;
   1868 
   1869 		killgssd_handle(clnt);
   1870 		GSSLOG0(1, "kgss_seal: RPC call times out\n");
   1871 		return (GSS_S_FAILURE);
   1872 	}
   1873 
   1874 	/* copy the rpc results into the return arguments */
   1875 
   1876 	if (minor_status != NULL)
   1877 		*minor_status = res.minor_status;
   1878 
   1879 	if (conf_state != NULL)
   1880 		*conf_state = res.conf_state;
   1881 
   1882 	if (output_message_buffer != NULL) {
   1883 		output_message_buffer->length =
   1884 				res.output_message_buffer.GSS_BUFFER_T_len;
   1885 
   1886 		output_message_buffer->value =
   1887 				(void *) MALLOC(output_message_buffer->length);
   1888 		(void) memcpy(output_message_buffer->value,
   1889 			res.output_message_buffer.GSS_BUFFER_T_val,
   1890 			output_message_buffer->length);
   1891 	}
   1892 
   1893 	/*
   1894 	 * free the memory allocated for the results and return with the status
   1895 	 * received in the rpc call
   1896 	 */
   1897 
   1898 	clnt_freeres(clnt, xdr_gss_seal_res, (caddr_t)&res);
   1899 	killgssd_handle(clnt);
   1900 	return (res.status);
   1901 }
   1902 
   1903 /*ARGSUSED*/
   1904 OM_uint32
   1905 kgss_seal(OM_uint32 *minor_status,
   1906 	const gss_ctx_id_t context_handle,
   1907 	int conf_req_flag,
   1908 	int qop_req,
   1909 	const gss_buffer_t input_message_buffer,
   1910 	int *conf_state,
   1911 	gss_buffer_t output_message_buffer)
   1912 
   1913 {
   1914 	if (context_handle == GSS_C_NO_CONTEXT)
   1915 		return (GSS_S_FAILURE);
   1916 	return (KGSS_SEAL(minor_status, context_handle,
   1917 		conf_req_flag, qop_req,
   1918 		input_message_buffer, conf_state,
   1919 		output_message_buffer));
   1920 }
   1921 
   1922 /*ARGSUSED*/
   1923 static OM_uint32
   1924 kgss_unseal_wrapped(void *private,
   1925 	OM_uint32 *minor_status,
   1926 	const gss_ctx_id_t ctx_handle,
   1927 	const gss_buffer_t input_message_buffer,
   1928 	gss_buffer_t output_message_buffer,
   1929 	int *conf_state,
   1930 	int *qop_state,
   1931 	OM_uint32 gssd_context_verifier)
   1932 {
   1933 	CLIENT *clnt;
   1934 
   1935 	gss_unseal_arg arg;
   1936 	gss_unseal_res res;
   1937 	gssd_ctx_id_t context_handle;
   1938 
   1939 	context_handle = (gssd_ctx_id_t)KCTX_TO_GSSD_CTX(ctx_handle);
   1940 
   1941 	/* get the client handle to GSSD */
   1942 
   1943 	if ((clnt = getgssd_handle()) == NULL) {
   1944 		GSSLOG(1, "kgss_unseal: can't connect to server on %s\n",
   1945 			server);
   1946 		return (GSS_S_FAILURE);
   1947 	}
   1948 
   1949 	/* copy the procedure arguments into the rpc arg parameter */
   1950 
   1951 	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gss_ctx_id_t);
   1952 	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
   1953 
   1954 	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
   1955 	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
   1956 	arg.gssd_context_verifier = gssd_context_verifier;
   1957 
   1958 	arg.input_message_buffer.GSS_BUFFER_T_len =
   1959 					(uint_t)input_message_buffer->length;
   1960 
   1961 	arg.input_message_buffer.GSS_BUFFER_T_val =
   1962 					(char *)input_message_buffer->value;
   1963 
   1964 	/* call the remote procedure */
   1965 
   1966 	bzero((caddr_t)&res, sizeof (res));
   1967 	if (gss_unseal_1(&arg, &res, clnt) != RPC_SUCCESS) {
   1968 
   1969 	/*
   1970 	 * if the RPC call times out, null out all return arguments, set
   1971 	 * minor_status to its maximum value, and return GSS_S_FAILURE
   1972 	 */
   1973 
   1974 		if (minor_status != NULL)
   1975 			*minor_status = DEFAULT_MINOR_STAT;
   1976 		if (output_message_buffer != NULL)
   1977 			output_message_buffer->length = 0;
   1978 		if (conf_state != NULL)
   1979 			*conf_state = 0;
   1980 		if (qop_state != NULL)
   1981 			*qop_state = 0;
   1982 
   1983 		killgssd_handle(clnt);
   1984 		GSSLOG0(1, "kgss_unseal: RPC call times out\n");
   1985 		return (GSS_S_FAILURE);
   1986 	}
   1987 
   1988 	/* copy the rpc results into the return arguments */
   1989 
   1990 	if (minor_status != NULL)
   1991 		*minor_status = res.minor_status;
   1992 
   1993 	if (output_message_buffer != NULL) {
   1994 		output_message_buffer->length =
   1995 				res.output_message_buffer.GSS_BUFFER_T_len;
   1996 
   1997 		output_message_buffer->value =
   1998 			(void *) MALLOC(output_message_buffer->length);
   1999 		(void) memcpy(output_message_buffer->value,
   2000 			res.output_message_buffer.GSS_BUFFER_T_val,
   2001 			output_message_buffer->length);
   2002 	}
   2003 
   2004 	if (conf_state != NULL)
   2005 		*conf_state = res.conf_state;
   2006 
   2007 	if (qop_state != NULL)
   2008 		*qop_state = res.qop_state;
   2009 
   2010 	/*
   2011 	 * free the memory allocated for the results and return with the
   2012 	 * status received in the rpc call
   2013 	 */
   2014 
   2015 	clnt_freeres(clnt, xdr_gss_unseal_res, (caddr_t)&res);
   2016 	killgssd_handle(clnt);
   2017 	return (res.status);
   2018 }
   2019 
   2020 OM_uint32
   2021 kgss_unseal(OM_uint32 *minor_status,
   2022 	const gss_ctx_id_t context_handle,
   2023 	const gss_buffer_t input_message_buffer,
   2024 	const gss_buffer_t output_message_buffer,
   2025 	int *conf_state,
   2026 	int *qop_state)
   2027 {
   2028 
   2029 	if (context_handle == GSS_C_NO_CONTEXT)
   2030 		return (GSS_S_FAILURE);
   2031 
   2032 	return (KGSS_UNSEAL(minor_status, context_handle, input_message_buffer,
   2033 		output_message_buffer, conf_state, qop_state));
   2034 }
   2035 
   2036 /* EXPORT DELETE END */
   2037 
   2038 OM_uint32
   2039 kgss_display_status(minor_status,
   2040 		status_value,
   2041 		status_type,
   2042 		mech_type,
   2043 		message_context,
   2044 		status_string,
   2045 		uid)
   2046 	OM_uint32 *minor_status;
   2047 	OM_uint32 status_value;
   2048 	int status_type;
   2049 	const gss_OID mech_type;
   2050 	int *message_context;
   2051 	gss_buffer_t status_string;
   2052 	uid_t uid;
   2053 {
   2054 	CLIENT *clnt;
   2055 
   2056 	gss_display_status_arg arg;
   2057 	gss_display_status_res res;
   2058 
   2059 	/* get the client handle to GSSD */
   2060 
   2061 	if ((clnt = getgssd_handle()) == NULL) {
   2062 	GSSLOG(1, "kgss_display_status: can't connect to server on %s\n",
   2063 			server);
   2064 		return (GSS_S_FAILURE);
   2065 	}
   2066 
   2067 	/* copy the procedure arguments into the rpc arg parameter */
   2068 
   2069 	arg.uid = (OM_uint32) uid;
   2070 
   2071 	arg.status_value = status_value;
   2072 	arg.status_type = status_type;
   2073 
   2074 	arg.mech_type.GSS_OID_len = (uint_t)(mech_type != GSS_C_NULL_OID ?
   2075 						mech_type->length : 0);
   2076 	arg.mech_type.GSS_OID_val = (char *)(mech_type != GSS_C_NULL_OID ?
   2077 						mech_type->elements : 0);
   2078 
   2079 	arg.message_context = *message_context;
   2080 
   2081 	/* call the remote procedure */
   2082 
   2083 	if (message_context != NULL)
   2084 		*message_context = 0;
   2085 	if (status_string != NULL) {
   2086 		status_string->length = 0;
   2087 		status_string->value = NULL;
   2088 	}
   2089 
   2090 	bzero((caddr_t)&res, sizeof (res));
   2091 	if (gss_display_status_1(&arg, &res, clnt) != RPC_SUCCESS) {
   2092 
   2093 	/*
   2094 	 * if the RPC call times out, null out all return arguments, set
   2095 	 * minor_status to its maximum value, and return GSS_S_FAILURE
   2096 	 */
   2097 
   2098 		if (minor_status != NULL)
   2099 			*minor_status = DEFAULT_MINOR_STAT;
   2100 
   2101 		killgssd_handle(clnt);
   2102 		GSSLOG0(1, "kgss_display_status: RPC call time out\n");
   2103 		return (GSS_S_FAILURE);
   2104 	}
   2105 
   2106 
   2107 	/* now process the results and pass them back to the caller */
   2108 
   2109 	if (res.status == GSS_S_COMPLETE) {
   2110 		if (minor_status != NULL)
   2111 			*minor_status = res.minor_status;
   2112 		if (message_context != NULL)
   2113 			*message_context = res.message_context;
   2114 		if (status_string != NULL) {
   2115 			status_string->length =
   2116 				(size_t)res.status_string.GSS_BUFFER_T_len;
   2117 			status_string->value =
   2118 				(void *) MALLOC(status_string->length);
   2119 			(void) memcpy(status_string->value,
   2120 				res.status_string.GSS_BUFFER_T_val,
   2121 				status_string->length);
   2122 		}
   2123 	}
   2124 
   2125 	clnt_freeres(clnt, xdr_gss_display_status_res, (caddr_t)&res);
   2126 	killgssd_handle(clnt);
   2127 	return (res.status);
   2128 }
   2129 
   2130 /*ARGSUSED*/
   2131 OM_uint32
   2132 kgss_indicate_mechs(minor_status,
   2133 			mech_set,
   2134 			uid)
   2135 	OM_uint32 *minor_status;
   2136 	gss_OID_set *mech_set;
   2137 	uid_t uid;
   2138 {
   2139 	CLIENT *clnt;
   2140 	void *arg;
   2141 	gss_indicate_mechs_res res;
   2142 	int i;
   2143 
   2144 	/* get the client handle to GSSD */
   2145 
   2146 	if ((clnt = getgssd_handle()) == NULL) {
   2147 	GSSLOG(1, "kgss_indicate_mechs: can't connect to server on %s\n",
   2148 			server);
   2149 		return (GSS_S_FAILURE);
   2150 	}
   2151 
   2152 	bzero((caddr_t)&res, sizeof (res));
   2153 	if (gss_indicate_mechs_1(&arg, &res, clnt) != RPC_SUCCESS) {
   2154 
   2155 	/*
   2156 	 * if the RPC call times out, null out all return arguments, set
   2157 	 * minor_status to its maximum value, and return GSS_S_FAILURE
   2158 	 */
   2159 
   2160 		if (minor_status != NULL)
   2161 			*minor_status = DEFAULT_MINOR_STAT;
   2162 		if (mech_set != NULL)
   2163 			*mech_set = NULL;
   2164 
   2165 		killgssd_handle(clnt);
   2166 		GSSLOG0(1, "kgss_indicate_mechs: RPC call times out\n");
   2167 		return (GSS_S_FAILURE);
   2168 	}
   2169 
   2170 	/* copy the rpc results into the return arguments */
   2171 
   2172 	if (minor_status != NULL)
   2173 		*minor_status = res.minor_status;
   2174 
   2175 	if (mech_set != NULL) {
   2176 		*mech_set = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
   2177 		(*mech_set)->count = res.mech_set.GSS_OID_SET_len;
   2178 		(*mech_set)->elements = (void *)
   2179 			MALLOC ((*mech_set)->count * sizeof (gss_OID_desc));
   2180 		for (i = 0; i < (*mech_set)->count; i++) {
   2181 			(*mech_set)->elements[i].length =
   2182 				res.mech_set.GSS_OID_SET_val[i].GSS_OID_len;
   2183 			(*mech_set)->elements[i].elements = (void *)
   2184 				MALLOC ((*mech_set)->elements[i].length);
   2185 			(void) memcpy((*mech_set)->elements[i].elements,
   2186 				res.mech_set.GSS_OID_SET_val[i].GSS_OID_val,
   2187 				(*mech_set)->elements[i].length);
   2188 		}
   2189 	}
   2190 
   2191 	/*
   2192 	 * free the memory allocated for the results and return with the status
   2193 	 * received in the rpc call
   2194 	 */
   2195 
   2196 	clnt_freeres(clnt, xdr_gss_indicate_mechs_res, (caddr_t)&res);
   2197 	killgssd_handle(clnt);
   2198 	return (res.status);
   2199 }
   2200 
   2201 
   2202 OM_uint32
   2203 kgss_inquire_cred_wrapped(minor_status,
   2204 		cred_handle,
   2205 		gssd_cred_verifier,
   2206 		name,
   2207 		lifetime,
   2208 		cred_usage,
   2209 		mechanisms,
   2210 		uid)
   2211 	OM_uint32 *minor_status;
   2212 	const gssd_cred_id_t cred_handle;
   2213 	OM_uint32 gssd_cred_verifier;
   2214 	gss_name_t *name;
   2215 	OM_uint32 *lifetime;
   2216 	int *cred_usage;
   2217 	gss_OID_set *mechanisms;
   2218 	uid_t uid;
   2219 {
   2220 	CLIENT *clnt;
   2221 
   2222 	OM_uint32 	minor_status_temp;
   2223 	gss_buffer_desc	external_name;
   2224 	gss_OID_desc	name_type;
   2225 	int		i;
   2226 
   2227 	gss_inquire_cred_arg arg;
   2228 	gss_inquire_cred_res res;
   2229 
   2230 	/*
   2231 	 * NULL the params here once
   2232 	 * If there are errors then we won't
   2233 	 * have to do it for every error
   2234 	 * case
   2235 	 */
   2236 	if (minor_status != NULL)
   2237 		*minor_status = DEFAULT_MINOR_STAT;
   2238 	if (name != NULL)
   2239 		*name = NULL;
   2240 	if (lifetime != NULL)
   2241 		*lifetime = 0;
   2242 	if (cred_usage != NULL)
   2243 		*cred_usage = 0;
   2244 	if (mechanisms != NULL)
   2245 		*mechanisms = NULL;
   2246 
   2247 	/* get the client handle to GSSD */
   2248 
   2249 	if ((clnt = getgssd_handle()) == NULL) {
   2250 		GSSLOG(1, "kgss_inquire_cred: can't connect to server on %s\n",
   2251 			server);
   2252 		return (GSS_S_FAILURE);
   2253 	}
   2254 
   2255 
   2256 	/* copy the procedure arguments into the rpc arg parameter */
   2257 
   2258 	arg.uid = (OM_uint32) uid;
   2259 
   2260 	arg.cred_handle.GSS_CRED_ID_T_len =
   2261 			cred_handle == (gssd_cred_id_t)GSS_C_NO_CREDENTIAL ?
   2262 			0 : (uint_t)sizeof (gssd_cred_id_t);
   2263 	arg.cred_handle.GSS_CRED_ID_T_val = (char *)&cred_handle;
   2264 	arg.gssd_cred_verifier = gssd_cred_verifier;
   2265 
   2266 	/* call the remote procedure */
   2267 
   2268 	bzero((caddr_t)&res, sizeof (res));
   2269 	if (gss_inquire_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
   2270 
   2271 		/*
   2272 		 * if the RPC call times out
   2273 		 * kill the handle and return GSS_S_FAILURE
   2274 		 * the parameters have been set to NULL already
   2275 		 */
   2276 
   2277 		killgssd_handle(clnt);
   2278 		GSSLOG0(1, "kgss_inquire_cred: RPC call times out\n");
   2279 		return (GSS_S_FAILURE);
   2280 	}
   2281 
   2282 	/* copy the rpc results into the return arguments */
   2283 
   2284 	if (minor_status != NULL)
   2285 		*minor_status = res.minor_status;
   2286 
   2287 	/* convert name from external to internal format */
   2288 
   2289 	if (name != NULL) {
   2290 		external_name.length = res.name.GSS_BUFFER_T_len;
   2291 		external_name.value = res.name.GSS_BUFFER_T_val;
   2292 
   2293 		/*
   2294 		 * we can pass a pointer to res structure
   2295 		 * since gss_import_name treats the name_type
   2296 		 * parameter as read only and performs a copy
   2297 		 */
   2298 
   2299 		name_type.length = res.name_type.GSS_OID_len;
   2300 		name_type.elements = (void *)res.name_type.GSS_OID_val;
   2301 
   2302 		if (gss_import_name(&minor_status_temp, &external_name,
   2303 			&name_type, name) != GSS_S_COMPLETE) {
   2304 
   2305 			*minor_status = (OM_uint32) minor_status_temp;
   2306 			clnt_freeres(clnt, xdr_gss_inquire_cred_res,
   2307 							(caddr_t)&res);
   2308 			killgssd_handle(clnt);
   2309 			GSSLOG0(1, "kgss_inquire_cred: import name fails\n");
   2310 			return ((OM_uint32) GSS_S_FAILURE);
   2311 		}
   2312 	}
   2313 
   2314 	if (lifetime != NULL)
   2315 		*lifetime = res.lifetime;
   2316 
   2317 	if (cred_usage != NULL)
   2318 		*cred_usage = res.cred_usage;
   2319 
   2320 	if (res.status == GSS_S_COMPLETE &&
   2321 		res.mechanisms.GSS_OID_SET_len != 0 &&
   2322 		mechanisms != NULL) {
   2323 		*mechanisms = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
   2324 		(*mechanisms)->count =
   2325 			(int)res.mechanisms.GSS_OID_SET_len;
   2326 		(*mechanisms)->elements = (gss_OID)
   2327 			MALLOC(sizeof (gss_OID_desc) * (*mechanisms)->count);
   2328 
   2329 		for (i = 0; i < (*mechanisms)->count; i++) {
   2330 		    (*mechanisms)->elements[i].length = (OM_uint32)
   2331 			res.mechanisms.GSS_OID_SET_val[i].GSS_OID_len;
   2332 		    (*mechanisms)->elements[i].elements =
   2333 			(void *) MALLOC((*mechanisms)->elements[i].length);
   2334 		    (void) memcpy((*mechanisms)->elements[i].elements,
   2335 			res.mechanisms.GSS_OID_SET_val[i].GSS_OID_val,
   2336 			(*mechanisms)->elements[i].length);
   2337 		}
   2338 	} else {
   2339 		if (res.status == GSS_S_COMPLETE &&
   2340 			mechanisms != NULL)
   2341 			(*mechanisms) = NULL;
   2342 	}
   2343 	/*
   2344 	 * free the memory allocated for the results and return with the status
   2345 	 * received in the rpc call
   2346 	 */
   2347 
   2348 	clnt_freeres(clnt, xdr_gss_inquire_cred_res, (caddr_t)&res);
   2349 	killgssd_handle(clnt);
   2350 	return (res.status);
   2351 
   2352 }
   2353 
   2354 OM_uint32
   2355 kgss_inquire_cred(minor_status,
   2356 			cred_handle,
   2357 			name,
   2358 			lifetime,
   2359 			cred_usage,
   2360 			mechanisms,
   2361 			uid)
   2362 	OM_uint32 *minor_status;
   2363 	const gss_cred_id_t cred_handle;
   2364 	gss_name_t *name;
   2365 	OM_uint32 *lifetime;
   2366 	int *cred_usage;
   2367 	gss_OID_set * mechanisms;
   2368 	uid_t uid;
   2369 {
   2370 
   2371 	OM_uint32 gssd_cred_verifier;
   2372 	OM_uint32 gssd_cred_handle;
   2373 
   2374 	gssd_cred_verifier = KCRED_TO_CREDV(cred_handle);
   2375 	gssd_cred_handle = KCRED_TO_CRED(cred_handle);
   2376 
   2377 	return (kgss_inquire_cred_wrapped(minor_status,
   2378 			gssd_cred_handle, gssd_cred_verifier,
   2379 			name, lifetime, cred_usage, mechanisms, uid));
   2380 }
   2381 
   2382 OM_uint32
   2383 kgss_inquire_cred_by_mech_wrapped(minor_status,
   2384 		cred_handle,
   2385 		gssd_cred_verifier,
   2386 		mech_type,
   2387 		uid)
   2388 	OM_uint32 *minor_status;
   2389 	gssd_cred_id_t cred_handle;
   2390 	OM_uint32 gssd_cred_verifier;
   2391 	gss_OID mech_type;
   2392 	uid_t uid;
   2393 {
   2394 	CLIENT *clnt;
   2395 
   2396 	gss_inquire_cred_by_mech_arg arg;
   2397 	gss_inquire_cred_by_mech_res res;
   2398 
   2399 	/* get the client handle to GSSD */
   2400 
   2401 	if ((clnt = getgssd_handle()) == NULL) {
   2402 		GSSLOG(1, "kgss_inquire_cred: can't connect to server on %s\n",
   2403 			server);
   2404 		return (GSS_S_FAILURE);
   2405 	}
   2406 
   2407 
   2408 	/* copy the procedure arguments into the rpc arg parameter */
   2409 
   2410 	arg.uid = (OM_uint32) uid;
   2411 
   2412 	arg.cred_handle.GSS_CRED_ID_T_len =
   2413 			cred_handle == (gssd_cred_id_t)GSS_C_NO_CREDENTIAL ?
   2414 			0 : (uint_t)sizeof (gssd_cred_id_t);
   2415 	arg.cred_handle.GSS_CRED_ID_T_val = (char *)&cred_handle;
   2416 	arg.gssd_cred_verifier = gssd_cred_verifier;
   2417 
   2418 	arg.mech_type.GSS_OID_len =
   2419 		(uint_t)(mech_type != GSS_C_NULL_OID ?
   2420 		mech_type->length : 0);
   2421 	arg.mech_type.GSS_OID_val =
   2422 		(char *)(mech_type != GSS_C_NULL_OID ?
   2423 		mech_type->elements : 0);
   2424 	/* call the remote procedure */
   2425 
   2426 	bzero((caddr_t)&res, sizeof (res));
   2427 	if (gss_inquire_cred_by_mech_1(&arg, &res, clnt) != RPC_SUCCESS) {
   2428 
   2429 	/*
   2430 	 * if the RPC call times out, null out all return arguments, set
   2431 	 * minor_status to its maximum value, and return GSS_S_FAILURE
   2432 	 */
   2433 
   2434 		if (minor_status != NULL)
   2435 			*minor_status = DEFAULT_MINOR_STAT;
   2436 		killgssd_handle(clnt);
   2437 		GSSLOG0(1, "kgss_inquire_cred: RPC call times out\n");
   2438 		return (GSS_S_FAILURE);
   2439 	}
   2440 
   2441 	/* copy the rpc results into the return arguments */
   2442 
   2443 	if (minor_status != NULL)
   2444 		*minor_status = res.minor_status;
   2445 
   2446 	clnt_freeres(clnt, xdr_gss_inquire_cred_by_mech_res, (caddr_t)&res);
   2447 	killgssd_handle(clnt);
   2448 	return (res.status);
   2449 
   2450 }
   2451 
   2452 OM_uint32
   2453 kgss_inquire_cred_by_mech(minor_status,
   2454 			cred_handle,
   2455 			mech_type,
   2456 			uid)
   2457 	OM_uint32 *minor_status;
   2458 	gss_cred_id_t cred_handle;
   2459 	gss_OID mech_type;
   2460 	uid_t uid;
   2461 {
   2462 
   2463 	OM_uint32 gssd_cred_verifier;
   2464 	OM_uint32 gssd_cred_handle;
   2465 
   2466 	gssd_cred_verifier = KCRED_TO_CREDV(cred_handle);
   2467 	gssd_cred_handle = KCRED_TO_CRED(cred_handle);
   2468 
   2469 	return (kgss_inquire_cred_by_mech_wrapped(minor_status,
   2470 			gssd_cred_handle, gssd_cred_verifier,
   2471 			mech_type, uid));
   2472 }
   2473 
   2474 OM_uint32
   2475 kgsscred_expname_to_unix_cred(expName, uidOut, gidOut, gids, gidsLen, uid)
   2476 	const gss_buffer_t expName;
   2477 	uid_t *uidOut;
   2478 	gid_t *gidOut;
   2479 	gid_t *gids[];
   2480 	int *gidsLen;
   2481 	uid_t uid;
   2482 {
   2483 	CLIENT *clnt;
   2484 	gsscred_expname_to_unix_cred_arg args;
   2485 	gsscred_expname_to_unix_cred_res res;
   2486 
   2487 	/* check input/output parameters */
   2488 	if (expName == NULL || expName->value == NULL)
   2489 		return (GSS_S_CALL_INACCESSIBLE_READ);
   2490 
   2491 	if (uidOut == NULL)
   2492 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
   2493 
   2494 	/* NULL out output parameters */
   2495 	*uidOut = UID_NOBODY;
   2496 	if (gidsLen)
   2497 		*gidsLen = 0;
   2498 
   2499 	if (gids)
   2500 		*gids = NULL;
   2501 
   2502 	/* get the client handle to gssd */
   2503 	if ((clnt = getgssd_handle()) == NULL)
   2504 	{
   2505 		GSSLOG(1, "kgsscred_expname_to_unix_cred:"
   2506 			" can't connect to server on %s\n", server);
   2507 		return (GSS_S_FAILURE);
   2508 	}
   2509 
   2510 	/* copy the procedure arguments */
   2511 	args.uid = uid;
   2512 	args.expname.GSS_BUFFER_T_val = expName->value;
   2513 	args.expname.GSS_BUFFER_T_len = expName->length;
   2514 
   2515 	/* null out the return buffer and call the remote proc */
   2516 	bzero(&res, sizeof (res));
   2517 
   2518 	if (gsscred_expname_to_unix_cred_1(&args, &res, clnt) != RPC_SUCCESS)
   2519 	{
   2520 		killgssd_handle(clnt);
   2521 		GSSLOG0(1,
   2522 			"kgsscred_expname_to_unix_cred: RPC call times out\n");
   2523 		return (GSS_S_FAILURE);
   2524 	}
   2525 
   2526 	/* copy the results into the result parameters */
   2527 	if (res.major == GSS_S_COMPLETE)
   2528 	{
   2529 		*uidOut = res.uid;
   2530 		if (gidOut)
   2531 			*gidOut = res.gid;
   2532 		if (gids && gidsLen)
   2533 		{
   2534 			*gids = res.gids.GSSCRED_GIDS_val;
   2535 			*gidsLen = res.gids.GSSCRED_GIDS_len;
   2536 			res.gids.GSSCRED_GIDS_val = NULL;
   2537 			res.gids.GSSCRED_GIDS_len = 0;
   2538 		}
   2539 	}
   2540 
   2541 	/* free RPC results */
   2542 	clnt_freeres(clnt, xdr_gsscred_expname_to_unix_cred_res, (caddr_t)&res);
   2543 	killgssd_handle(clnt);
   2544 
   2545 	return (res.major);
   2546 } /* kgsscred_expname_to_unix_cred */
   2547 
   2548 OM_uint32
   2549 kgsscred_name_to_unix_cred(intName, mechType, uidOut, gidOut, gids,
   2550 				gidsLen, uid)
   2551 	const gss_name_t intName;
   2552 	const gss_OID mechType;
   2553 	uid_t *uidOut;
   2554 	gid_t *gidOut;
   2555 	gid_t *gids[];
   2556 	int *gidsLen;
   2557 	uid_t uid;
   2558 {
   2559 	CLIENT *clnt;
   2560 	gsscred_name_to_unix_cred_arg args;
   2561 	gsscred_name_to_unix_cred_res res;
   2562 	OM_uint32 major, minor;
   2563 	gss_OID nameOid;
   2564 	gss_buffer_desc flatName = GSS_C_EMPTY_BUFFER;
   2565 
   2566 	/* check the input/output parameters */
   2567 	if (intName == NULL || mechType == NULL)
   2568 		return (GSS_S_CALL_INACCESSIBLE_READ);
   2569 
   2570 	if (uidOut == NULL)
   2571 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
   2572 
   2573 	/* NULL out the output parameters */
   2574 	*uidOut = UID_NOBODY;
   2575 	if (gids)
   2576 		*gids = NULL;
   2577 
   2578 	if (gidsLen)
   2579 		*gidsLen = 0;
   2580 
   2581 	/* get the client handle to gssd */
   2582 	if ((clnt = getgssd_handle()) == NULL)
   2583 	{
   2584 		GSSLOG(1,
   2585 		"kgsscred_name_to_unix_cred: can't connect to server %s\n",
   2586 				server);
   2587 		return (GSS_S_FAILURE);
   2588 	}
   2589 
   2590 	/* convert the name to flat representation */
   2591 	if ((major = gss_display_name(&minor, intName, &flatName, &nameOid))
   2592 			!= GSS_S_COMPLETE)
   2593 	{
   2594 		killgssd_handle(clnt);
   2595 		GSSLOG0(1, "kgsscred_name_to_unix_cred: display name failed\n");
   2596 		return (major);
   2597 	}
   2598 
   2599 	/* set the rpc parameters */
   2600 	args.uid = uid;
   2601 	args.pname.GSS_BUFFER_T_len = flatName.length;
   2602 	args.pname.GSS_BUFFER_T_val = flatName.value;
   2603 	args.name_type.GSS_OID_len = nameOid->length;
   2604 	args.name_type.GSS_OID_val = nameOid->elements;
   2605 	args.mech_type.GSS_OID_len = mechType->length;
   2606 	args.mech_type.GSS_OID_val = mechType->elements;
   2607 
   2608 	/* call the remote procedure */
   2609 	bzero(&res, sizeof (res));
   2610 	if (gsscred_name_to_unix_cred_1(&args, &res, clnt) != RPC_SUCCESS) {
   2611 		killgssd_handle(clnt);
   2612 		(void) gss_release_buffer(&minor, &flatName);
   2613 		GSSLOG0(1, "kgsscred_name_to_unix_cred: RPC call times out\n");
   2614 		return (GSS_S_FAILURE);
   2615 	}
   2616 
   2617 	/* delete the flat name buffer */
   2618 	(void) gss_release_buffer(&minor, &flatName);
   2619 
   2620 	/* copy the output parameters on output */
   2621 	if (res.major == GSS_S_COMPLETE) {
   2622 		*uidOut = res.uid;
   2623 
   2624 		if (gidOut)
   2625 			*gidOut = res.gid;
   2626 		if (gids && gidsLen) {
   2627 			*gids = res.gids.GSSCRED_GIDS_val;
   2628 			*gidsLen = res.gids.GSSCRED_GIDS_len;
   2629 			res.gids.GSSCRED_GIDS_val = NULL;
   2630 			res.gids.GSSCRED_GIDS_len = 0;
   2631 		}
   2632 	}
   2633 
   2634 	/* delete RPC allocated memory */
   2635 	clnt_freeres(clnt, xdr_gsscred_name_to_unix_cred_res, (caddr_t)&res);
   2636 	killgssd_handle(clnt);
   2637 
   2638 	return (res.major);
   2639 } /* kgsscred_name_to_unix_cred */
   2640 
   2641 OM_uint32
   2642 kgss_get_group_info(puid, gidOut, gids, gidsLen, uid)
   2643 	const uid_t puid;
   2644 	gid_t *gidOut;
   2645 	gid_t *gids[];
   2646 	int *gidsLen;
   2647 	uid_t uid;
   2648 {
   2649 	CLIENT *clnt;
   2650 	gss_get_group_info_arg args;
   2651 	gss_get_group_info_res res;
   2652 
   2653 
   2654 	/* check the output parameters */
   2655 	if (gidOut == NULL || gids == NULL || gidsLen == NULL)
   2656 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
   2657 
   2658 	/* get the client GSSD handle */
   2659 	if ((clnt = getgssd_handle()) == NULL) {
   2660 		GSSLOG(1,
   2661 			"kgss_get_group_info: can't connect to server on %s\n",
   2662 			server);
   2663 		return (GSS_S_FAILURE);
   2664 	}
   2665 
   2666 	/* set the input parameters */
   2667 	args.uid = uid;
   2668 	args.puid = puid;
   2669 
   2670 	/* call the remote procedure */
   2671 	bzero(&res, sizeof (res));
   2672 	if (gss_get_group_info_1(&args, &res, clnt) != RPC_SUCCESS) {
   2673 		killgssd_handle(clnt);
   2674 		GSSLOG0(1, "kgss_get_group_info: RPC call times out\n");
   2675 		return (GSS_S_FAILURE);
   2676 	}
   2677 
   2678 	/* copy the results */
   2679 	if (res.major == GSS_S_COMPLETE) {
   2680 		*gidOut = res.gid;
   2681 		*gids = res.gids.GSSCRED_GIDS_val;
   2682 		*gidsLen = res.gids.GSSCRED_GIDS_len;
   2683 		res.gids.GSSCRED_GIDS_val = NULL;
   2684 		res.gids.GSSCRED_GIDS_len = 0;
   2685 	}
   2686 
   2687 	/* no results to free */
   2688 	killgssd_handle(clnt);
   2689 
   2690 	return (res.major);
   2691 } /* kgss_get_group_info */
   2692 
   2693 static char *
   2694 kgss_get_kmod(gss_OID mech_oid)
   2695 {
   2696 	CLIENT *clnt;
   2697 	gss_get_kmod_arg args;
   2698 	gss_get_kmod_res res;
   2699 
   2700 
   2701 	/* get the client GSSD handle */
   2702 	if ((clnt = getgssd_handle()) == NULL) {
   2703 		GSSLOG(1, "kgss_get_kmod: can't connect to server on %s\n",
   2704 			server);
   2705 		return (NULL);
   2706 	}
   2707 
   2708 	/* set the input parameters */
   2709 	args.mech_oid.GSS_OID_len = mech_oid->length;
   2710 	args.mech_oid.GSS_OID_val = mech_oid->elements;
   2711 
   2712 	/* call the remote procedure */
   2713 	bzero(&res, sizeof (res));
   2714 	if (gss_get_kmod_1(&args, &res, clnt) != RPC_SUCCESS) {
   2715 		killgssd_handle(clnt);
   2716 		GSSLOG0(1, "gss_get_kmod_1: RPC call times out\n");
   2717 		return (NULL);
   2718 	}
   2719 	/* no results to free */
   2720 	killgssd_handle(clnt);
   2721 
   2722 	if (res.module_follow == TRUE) {
   2723 		return (res.gss_get_kmod_res_u.modname);
   2724 	} else
   2725 		return (NULL);
   2726 } /* kgss_get_kmod */
   2727 
   2728 static gss_mechanism	kgss_mech_head;
   2729 static gss_mechanism	kgss_mech_tail;
   2730 kmutex_t	__kgss_mech_lock;
   2731 
   2732 /*
   2733  * See if there is kernel mechanism module, and if so, attempt to
   2734  * load it and reset the pointer (gss_mechanism) to the sign/seal/etc.
   2735  * entry points to that of the kernel module.
   2736  */
   2737 static void
   2738 __kgss_reset_mech(gss_mechanism *mechp, gss_OID mech_oid)
   2739 {
   2740 	gss_mechanism mech;
   2741 	char *kmod;
   2742 
   2743 	/*
   2744 	 * We can search the list without a mutex, becuase the list never
   2745 	 * shrinks and we always add to the end.
   2746 	 */
   2747 	mech = __kgss_get_mechanism(mech_oid);
   2748 	if (mech) {
   2749 		*mechp = mech;
   2750 		return;
   2751 	}
   2752 
   2753 	/*
   2754 	 * Get the module name from the kernel.
   2755 	 */
   2756 	kmod = kgss_get_kmod(mech_oid);
   2757 
   2758 	if (kmod) {
   2759 		extern int modload(const char *, const char *);
   2760 		if (modload("misc/kgss", kmod) < 0) {
   2761 			/*
   2762 			 * Modload of 'kmod' failed, so log an
   2763 			 * appropriate comment
   2764 			 */
   2765 			cmn_err(CE_NOTE, "kgss_reset_mech: Algorithm modload "
   2766 				"(%s) failed. Userland gssd will now handle "
   2767 				"all GSSAPI calls, which may result in "
   2768 				"reduced performance.\n", kmod);
   2769 		};
   2770 
   2771 		/*
   2772 		 * Allocated in the XDR routine called by gss_get_kmod_1().
   2773 		 */
   2774 		FREE(kmod, strlen(kmod)+1);
   2775 
   2776 		mech = __kgss_get_mechanism(mech_oid);
   2777 		if (mech) {
   2778 			*mechp = mech;
   2779 		}
   2780 
   2781 		/*
   2782 		 * If for some reason the module load didn't take,
   2783 		 * we return anyway and hope that the next context
   2784 		 * creation succeeds.
   2785 		 */
   2786 		return;
   2787 	}
   2788 
   2789 
   2790 	/*
   2791 	 * No kernel module, so enter this mech oid into the list
   2792 	 * using the default sign/seal/etc. operations that upcall to
   2793 	 * gssd.
   2794 	 */
   2795 	mutex_enter(&__kgss_mech_lock);
   2796 	mech = __kgss_get_mechanism(mech_oid);
   2797 	if (mech) {
   2798 		mutex_exit(&__kgss_mech_lock);
   2799 		*mechp = mech;
   2800 		return;
   2801 	}
   2802 
   2803 	/*
   2804 	 * Allocate space for the mechanism entry.
   2805 	 */
   2806 	mech = kmem_zalloc(sizeof (struct gss_config), KM_SLEEP);
   2807 
   2808 	/*
   2809 	 * Copy basic information from default mechanism struct.
   2810 	 */
   2811 	*mech = default_gc;
   2812 
   2813 	/*
   2814 	 * Record the real mech OID.
   2815 	 */
   2816 	mech->mech_type.length = mech_oid->length;
   2817 	mech->mech_type.elements = MALLOC(mech_oid->length);
   2818 	bcopy(mech_oid->elements,  mech->mech_type.elements, mech_oid->length);
   2819 
   2820 	/*
   2821 	 * Add it to the table.
   2822 	 */
   2823 	__kgss_add_mechanism(mech);
   2824 	mutex_exit(&__kgss_mech_lock);
   2825 	*mechp = mech;
   2826 }
   2827 
   2828 /*
   2829  * Called with __kgss_mech_lock held.
   2830  */
   2831 void
   2832 __kgss_add_mechanism(gss_mechanism mech)
   2833 {
   2834 	gss_mechanism tmp;
   2835 
   2836 	tmp = kgss_mech_tail;
   2837 	kgss_mech_tail = mech;
   2838 
   2839 	if (tmp != NULL)
   2840 		tmp->next = mech;
   2841 
   2842 	if (kgss_mech_head == NULL)
   2843 		kgss_mech_head = mech;
   2844 }
   2845 
   2846 /*
   2847  *  given the mechs_array and a mechanism OID, return the
   2848  *  pointer to the mechanism, or NULL if that mechanism is
   2849  *  not supported.
   2850  */
   2851 gss_mechanism
   2852 __kgss_get_mechanism(gss_OID type)
   2853 {
   2854 	gss_mechanism mech;
   2855 
   2856 	mech = kgss_mech_head;
   2857 
   2858 	/*
   2859 	 * Note that a reader can scan this list without the mutex held.
   2860 	 * This is safe because we always append, and never shrink the list.
   2861 	 * Moreover, the entry is fully initialized before it is ever
   2862 	 * added to the list.
   2863 	 */
   2864 	while (mech != NULL) {
   2865 		if ((mech->mech_type.length == type->length) &&
   2866 		    (bcmp(mech->mech_type.elements, type->elements,
   2867 		    type->length) == 0))
   2868 			return (mech);
   2869 
   2870 		mech = mech->next;
   2871 	}
   2872 	return (NULL);
   2873 }
   2874