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