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