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 OM_uint32
1438 kgss_seal_wrapped(
1439         minor_status,
1440         context_handle,
1441         conf_req_flag,
1442         qop_req,
1443         input_message_buffer,
1444         conf_state,
1445         output_message_buffer,
1446         gssd_context_verifier)
1447 
1448         OM_uint32 *minor_status;
1449         gssd_ctx_id_t context_handle;
1450         OM_uint32 gssd_context_verifier;
1451         int conf_req_flag;
1452         int qop_req;
1453         gss_buffer_t input_message_buffer;
1454         int *conf_state;
1455         gss_buffer_t output_message_buffer;
1456 {
1457         gss_seal_arg arg;
1458         gss_seal_res res;
1459 
1460         /* get the client handle to GSSD */
1461 
1462         if ((clnt = getgssd_handle()) == NULL) {
1463                 clnt_pcreateerror(server);
1464                 return (GSS_S_FAILURE);
1465         }
1466 
1467         /* copy the procedure arguments into the rpc arg parameter */
1468 
1469 
1470         arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
1471         arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
1472         arg.gssd_context_verifier = gssd_context_verifier;
1473 
1474         arg.conf_req_flag = conf_req_flag;
1475 
1476         arg.qop_req = qop_req;
1477 
1478         arg.input_message_buffer.GSS_BUFFER_T_len =
1479                                 (uint_t)input_message_buffer->length;
1480 
1481         arg.input_message_buffer.GSS_BUFFER_T_val =
1482                                 (char *)input_message_buffer->value;
1483 
1484         /* call the remote procedure */
1485 
1486         memset(&res, 0, sizeof (res));
1487         if (gss_seal_1(&arg, &res, clnt) != RPC_SUCCESS) {
1488 
1489         /*
1490          * if the RPC call times out, null out all return arguments,
1491          * set minor_status to its maximum value, and return GSS_S_FAILURE
1492          */
1493 
1494                 if (minor_status != NULL)
1495                         *minor_status = DEFAULT_MINOR_STAT;
1496                 if (conf_state != NULL)
1497                         *conf_state = 0;
1498                 if (output_message_buffer != NULL)
1499                         output_message_buffer->length = 0;
1500 
1501                 return (GSS_S_FAILURE);
1502         }
1503 
1504         /* copy the rpc results into the return arguments */
1505 
1506         if (minor_status != NULL)
1507                 *minor_status = res.minor_status;
1508 
1509         if (conf_state != NULL)
1510                 *conf_state = res.conf_state;
1511 
1512         if (output_message_buffer != NULL) {
1513                 output_message_buffer->length =
1514                                 res.output_message_buffer.GSS_BUFFER_T_len;
1515 
1516                 output_message_buffer->value =
1517                                 (void *) MALLOC(output_message_buffer->length);
1518                 memcpy(output_message_buffer->value,
1519                         res.output_message_buffer.GSS_BUFFER_T_val,
1520                         output_message_buffer->length);
1521         }
1522 
1523         /*
1524          * free the memory allocated for the results and return with the status
1525          * received in the rpc call
1526          */
1527 
1528         clnt_freeres(clnt, xdr_gss_seal_res, (caddr_t)&res);
1529         return (res.status);
1530 }
1531 
1532 OM_uint32
1533 kgss_seal(OM_uint32 *minor_status,
1534                 gss_ctx_id_t context_handle,
1535                 int conf_req_flag,
1536                 int qop_req,
1537                 gss_buffer_t input_message_buffer,
1538                 int *conf_state,
1539                 gss_buffer_t output_message_buffer)
1540 
1541 {
1542                 if (context_handle == GSS_C_NO_CONTEXT)
1543                         return (GSS_S_FAILURE);
1544 
1545                 return (KGSS_SEAL(minor_status, context_handle,
1546                         conf_req_flag, qop_req,
1547                         input_message_buffer,
1548                         conf_state, output_message_buffer));
1549 }
1550 
1551 OM_uint32
1552 kgss_unseal_wrapped(minor_status,
1553                 context_handle,
1554                 input_message_buffer,
1555                 output_message_buffer,
1556                 conf_state,
1557                 qop_state,
1558                 gssd_context_verifier)
1559         OM_uint32 *minor_status;
1560         gssd_ctx_id_t context_handle;
1561         OM_uint32 gssd_context_verifier;
1562         gss_buffer_t input_message_buffer;
1563         gss_buffer_t output_message_buffer;
1564         int *conf_state;
1565         int *qop_state;
1566 {
1567         gss_unseal_arg arg;
1568         gss_unseal_res res;
1569 
1570         /* get the client handle to GSSD */
1571 
1572         if ((clnt = getgssd_handle()) == NULL) {
1573                 clnt_pcreateerror(server);
1574                 return (GSS_S_FAILURE);
1575         }
1576 
1577         /* copy the procedure arguments into the rpc arg parameter */
1578 
1579 
1580         arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
1581         arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
1582         arg.gssd_context_verifier = gssd_context_verifier;
1583 
1584         arg.input_message_buffer.GSS_BUFFER_T_len =
1585                                 (uint_t)input_message_buffer->length;
1586 
1587         arg.input_message_buffer.GSS_BUFFER_T_val =
1588                                 (char *)input_message_buffer->value;
1589 
1590 /* call the remote procedure */
1591 
1592         memset(&res, 0, sizeof (res));
1593         if (gss_unseal_1(&arg, &res, clnt) != RPC_SUCCESS) {
1594 
1595         /*
1596          * if the RPC call times out, null out all return arguments,
1597          * set minor_status to its maximum value, and return GSS_S_FAILURE
1598          */
1599 
1600                 if (minor_status != NULL)
1601                         *minor_status = DEFAULT_MINOR_STAT;
1602                 if (output_message_buffer != NULL)
1603                         output_message_buffer->length = 0;
1604                 if (conf_state != NULL)
1605                         *conf_state = 0;
1606                 if (qop_state != NULL)
1607                         *qop_state = 0;
1608 
1609                 return (GSS_S_FAILURE);
1610         }
1611 
1612         /* copy the rpc results into the return arguments */
1613 
1614         if (minor_status != NULL)
1615                 *minor_status = res.minor_status;
1616 
1617         if (output_message_buffer != NULL) {
1618                 output_message_buffer->length =
1619                                 res.output_message_buffer.GSS_BUFFER_T_len;
1620 
1621                 output_message_buffer->value =
1622                         (void *) MALLOC(output_message_buffer->length);
1623                 memcpy(output_message_buffer->value,
1624                         res.output_message_buffer.GSS_BUFFER_T_val,
1625                         output_message_buffer->length);
1626         }
1627 
1628         if (conf_state != NULL)
1629                 *conf_state = res.conf_state;
1630 
1631         if (qop_state != NULL)
1632                 *qop_state = res.qop_state;
1633 
1634         /*
1635          * free the memory allocated for the results and return with the status
1636          * received in the rpc call
1637          */
1638 
1639         clnt_freeres(clnt, xdr_gss_unseal_res, (caddr_t)&res);
1640         return (res.status);
1641 }
1642 
1643 OM_uint32
1644 kgss_unseal(OM_uint32 *minor_status,
1645         gss_ctx_id_t context_handle,
1646         gss_buffer_t input_message_buffer,
1647         gss_buffer_t output_message_buffer,
1648         int *conf_state,
1649         int *qop_state)
1650 {
1651                 if (context_handle == GSS_C_NO_CONTEXT)
1652                         return (GSS_S_FAILURE);
1653 
1654                 return (KGSS_UNSEAL(minor_status, context_handle,
1655                     input_message_buffer, output_message_buffer,
1656                     conf_state, qop_state));
1657 }
1658 
1659 OM_uint32
1660 kgss_display_status(minor_status,
1661                 status_value,
1662                 status_type,
1663                 mech_type,
1664                 message_context,
1665                 status_string,
1666                 uid)
1667         OM_uint32 *minor_status;
1668         OM_uint32 status_value;
1669         int status_type;
1670         gss_OID mech_type;
1671         int *message_context;
1672         gss_buffer_t status_string;
1673         uid_t uid;
1674 {
1675         gss_display_status_arg arg;
1676         gss_display_status_res res;
1677 
1678         /* get the client handle to GSSD */
1679 
1680         if ((clnt = getgssd_handle()) == NULL) {
1681                 clnt_pcreateerror(server);
1682                 return (GSS_S_FAILURE);
1683         }
1684 
1685         /* copy the procedure arguments into the rpc arg parameter */
1686 
1687         arg.uid = (OM_uint32) uid;
1688 
1689         arg.status_value = status_value;
1690         arg.status_type = status_type;
1691 
1692         arg.mech_type.GSS_OID_len = (uint_t)(mech_type != GSS_C_NULL_OID ?
1693                                         mech_type->length : 0);
1694         arg.mech_type.GSS_OID_val = (char *)(mech_type != GSS_C_NULL_OID ?
1695                                         mech_type->elements : 0);
1696 
1697         arg.message_context = *message_context;
1698 
1699         /* call the remote procedure */
1700 
1701         if (message_context != NULL)
1702                 *message_context = 0;
1703         if (status_string != NULL) {
1704                 status_string->length = 0;
1705                 status_string->value = NULL;
1706         }
1707 
1708         memset(&res, 0, sizeof (res));
1709         if (gss_display_status_1(&arg, &res, clnt) != RPC_SUCCESS) {
1710 
1711         /*
1712          * if the RPC call times out, null out all return arguments,
1713          * set minor_status to its maximum value, and return GSS_S_FAILURE
1714          */
1715 
1716                 if (minor_status != NULL)
1717                         *minor_status = DEFAULT_MINOR_STAT;
1718 
1719                 return (GSS_S_FAILURE);
1720         }
1721 
1722         if (minor_status != NULL)
1723                 *minor_status = res.minor_status;
1724 
1725         /* now process the results and pass them back to the caller */
1726 
1727         if (res.status == GSS_S_COMPLETE) {
1728                 if (message_context != NULL)
1729                         *message_context = res.message_context;
1730                 if (status_string != NULL) {
1731                         status_string->length =
1732                                 (size_t)res.status_string.GSS_BUFFER_T_len;
1733                         status_string->value =
1734                                 (void *)MALLOC(status_string->length);
1735                         memcpy(status_string->value,
1736                                 res.status_string.GSS_BUFFER_T_val,
1737                                 status_string->length);
1738                 }
1739         }
1740 
1741         clnt_freeres(clnt, xdr_gss_display_status_res, (caddr_t)&res);
1742         return (res.status);
1743 }
1744 
1745 /*ARGSUSED*/
1746 OM_uint32
1747 kgss_indicate_mechs(minor_status,
1748                 mech_set,
1749                 uid)
1750         OM_uint32 *minor_status;
1751         gss_OID_set *mech_set;
1752         uid_t uid;
1753 {
1754         void *arg;
1755         gss_indicate_mechs_res res;
1756         int i;
1757 
1758         /* get the client handle to GSSD */
1759 
1760         if ((clnt = getgssd_handle()) == NULL) {
1761                 clnt_pcreateerror(server);
1762                 return (GSS_S_FAILURE);
1763         }
1764 
1765         memset(&res, 0, sizeof (res));
1766         if (gss_indicate_mechs_1(&arg, &res, clnt) != RPC_SUCCESS) {
1767 
1768         /*
1769          * if the RPC call times out, null out all return arguments,
1770          * set minor_status to its maximum value, and return GSS_S_FAILURE
1771          */
1772 
1773                 if (minor_status != NULL)
1774                         *minor_status = DEFAULT_MINOR_STAT;
1775                 if (mech_set != NULL)
1776                         *mech_set = NULL;
1777 
1778                 return (GSS_S_FAILURE);
1779         }
1780 
1781         /* copy the rpc results into the return arguments */
1782 
1783         if (minor_status != NULL)
1784                 *minor_status = res.minor_status;
1785 
1786         if (mech_set != NULL) {
1787                 *mech_set = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
1788                 (*mech_set)->count = res.mech_set.GSS_OID_SET_len;
1789                 (*mech_set)->elements = (void *)
1790                         MALLOC ((*mech_set)->count * sizeof (gss_OID_desc));
1791                 for (i = 0; i < (*mech_set)->count; i++) {
1792                         (*mech_set)->elements[i].length =
1793                                 res.mech_set.GSS_OID_SET_val[i].GSS_OID_len;
1794                         (*mech_set)->elements[i].elements = (void *)
1795                                 MALLOC ((*mech_set)->elements[i].length);
1796                         memcpy ((*mech_set)->elements[i].elements,
1797                                 res.mech_set.GSS_OID_SET_val[i].GSS_OID_val,
1798                                 (*mech_set)->elements[i].length);
1799                 }
1800         }
1801 
1802         /*
1803          * free the memory allocated for the results and return with the status
1804          * received in the rpc call
1805          */
1806 
1807         clnt_freeres(clnt, xdr_gss_indicate_mechs_res, (caddr_t)&res);
1808         return (res.status);
1809 }
1810 
1811 
1812 OM_uint32
1813 kgss_inquire_cred_wrapped(minor_status,
1814                         cred_handle,
1815                         gssd_cred_verifier,
1816                         name,
1817                         lifetime,
1818                         cred_usage,
1819                         mechanisms,
1820                         uid)
1821         OM_uint32 *minor_status;
1822         gssd_cred_id_t cred_handle;
1823         OM_uint32 gssd_cred_verifier;
1824         gss_name_t *name;
1825         OM_uint32 *lifetime;
1826         int *cred_usage;
1827         gss_OID_set *mechanisms;
1828         uid_t uid;
1829 {
1830         OM_uint32 minor_status_temp;
1831         gss_buffer_desc external_name;
1832         gss_OID name_type;
1833         int i;
1834 
1835         gss_inquire_cred_arg arg;
1836         gss_inquire_cred_res res;
1837 
1838         /* get the client handle to GSSD */
1839 
1840         if ((clnt = getgssd_handle()) == NULL) {
1841                 clnt_pcreateerror(server);
1842                 return (GSS_S_FAILURE);
1843         }
1844 
1845 
1846         /* copy the procedure arguments into the rpc arg parameter */
1847 
1848         arg.uid = (OM_uint32) uid;
1849 
1850         arg.cred_handle.GSS_CRED_ID_T_len =
1851                         cred_handle == GSSD_NO_CREDENTIAL ?
1852                         0 : (uint_t)sizeof (gssd_cred_id_t);
1853         arg.cred_handle.GSS_CRED_ID_T_val = (char *)&cred_handle;
1854         arg.gssd_cred_verifier = gssd_cred_verifier;
1855 
1856         /* call the remote procedure */
1857 
1858         memset(&res, 0, sizeof (res));
1859         if (gss_inquire_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
1860 
1861         /*
1862          * if the RPC call times out, null out all return arguments,
1863          * set minor_status to its maximum value, and return GSS_S_FAILURE
1864          */
1865 
1866                 if (minor_status != NULL)
1867                         *minor_status = DEFAULT_MINOR_STAT;
1868                 if (name != NULL)
1869                         *name = NULL;
1870                 if (lifetime != NULL)
1871                         *lifetime = 0;
1872                 if (cred_usage != NULL)
1873                         *cred_usage = 0;
1874                 if (mechanisms != NULL)
1875                         *mechanisms = NULL;
1876 
1877                 return (GSS_S_FAILURE);
1878         }
1879 
1880         /* copy the rpc results into the return arguments */
1881 
1882         if (minor_status != NULL)
1883                 *minor_status = res.minor_status;
1884 
1885         /* convert name from external to internal format */
1886 
1887         if (name != NULL) {
1888                 external_name.length = res.name.GSS_BUFFER_T_len;
1889                 external_name.value = res.name.GSS_BUFFER_T_val;
1890 
1891                 /*
1892                  * we have to allocate a name_type descriptor and
1893                  * elements storage, since gss_import_name() only
1894                  * stores a pointer to the name_type info in the
1895                  * union_name struct
1896                  */
1897 
1898                 name_type = (gss_OID) MALLOC(sizeof (gss_OID_desc));
1899 
1900                 name_type->length = res.name_type.GSS_OID_len;
1901                 name_type->elements = (void *) MALLOC(name_type->length);
1902                 memcpy(name_type->elements, res.name_type.GSS_OID_val,
1903                         name_type->length);
1904 
1905                 if (gss_import_name(&minor_status_temp, &external_name,
1906                         name_type, name) != GSS_S_COMPLETE) {
1907 
1908                         *minor_status = (OM_uint32) minor_status_temp;
1909                         gss_release_buffer(&minor_status_temp, &external_name);
1910 
1911                         clnt_freeres(clnt, xdr_gss_inquire_cred_res,
1912                                                         (caddr_t)&res);
1913                         return ((OM_uint32) GSS_S_FAILURE);
1914                 }
1915         }
1916 
1917         if (lifetime != NULL)
1918                 *lifetime = res.lifetime;
1919 
1920         if (cred_usage != NULL)
1921                 *cred_usage = res.cred_usage;
1922 
1923         if (mechanisms != NULL) {
1924                 *mechanisms =
1925                         (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
1926                 if (res.mechanisms.GSS_OID_SET_len != 0) {
1927                         (*mechanisms)->count =
1928                                         (int)res.mechanisms.GSS_OID_SET_len;
1929                         (*mechanisms)->elements = (gss_OID)
1930                                 MALLOC(sizeof (gss_OID) * (*mechanisms)->count);
1931 
1932                         for (i = 0; i < (*mechanisms)->count; i++) {
1933                                 (*mechanisms)->elements[i].length = (OM_uint32)
1934                                 res.mechanisms.GSS_OID_SET_val[i].GSS_OID_len;
1935                                 (*mechanisms)->elements[i].elements = (void *)
1936                                 MALLOC((*mechanisms)->elements[i].length);
1937                                 memcpy((*mechanisms)->elements[i].elements,
1938                                 res.mechanisms.GSS_OID_SET_val[i].GSS_OID_val,
1939                                 (*mechanisms)->elements[i].length);
1940                         }
1941                 } else
1942                         (*mechanisms)->count = 0;
1943         }
1944 
1945         /*
1946          * free the memory allocated for the results and return with the status
1947          * received in the rpc call
1948          */
1949 
1950         clnt_freeres(clnt, xdr_gss_inquire_cred_res, (caddr_t)&res);
1951         return (res.status);
1952 }
1953 
1954 
1955 OM_uint32
1956 kgss_inquire_cred(minor_status,
1957                         cred_handle,
1958                         name,
1959                         lifetime,
1960                         cred_usage,
1961                         mechanisms,
1962                         uid)
1963         OM_uint32 *minor_status;
1964         gss_cred_id_t cred_handle;
1965         gss_name_t *name;
1966         OM_uint32 *lifetime;
1967         int *cred_usage;
1968         gss_OID_set * mechanisms;
1969         uid_t uid;
1970 {
1971 
1972         OM_uint32 gssd_cred_verifier;
1973         gssd_cred_id_t gssd_cred_handle;
1974 
1975                 gssd_cred_verifier = KCRED_TO_CREDV(cred_handle);
1976                 gssd_cred_handle = KCRED_TO_CRED(cred_handle);
1977 
1978                 return (kgss_inquire_cred_wrapped(minor_status,
1979                                 gssd_cred_handle, gssd_cred_verifier,
1980                                 name, lifetime, cred_usage, mechanisms, uid));
1981 }
1982 
1983 
1984 OM_uint32
1985 kgss_inquire_cred_by_mech_wrapped(minor_status,
1986                         cred_handle,
1987                         gssd_cred_verifier,
1988                         mech_type,
1989                         uid)
1990         OM_uint32 *minor_status;
1991         gssd_cred_id_t cred_handle;
1992         OM_uint32 gssd_cred_verifier;
1993         gss_OID mech_type;
1994         uid_t uid;
1995 {
1996         OM_uint32 minor_status_temp;
1997 
1998         gss_inquire_cred_by_mech_arg arg;
1999         gss_inquire_cred_by_mech_res res;
2000 
2001         /* get the client handle to GSSD */
2002 
2003         if ((clnt = getgssd_handle()) == NULL) {
2004                 clnt_pcreateerror(server);
2005                 return (GSS_S_FAILURE);
2006         }
2007 
2008 
2009         /* copy the procedure arguments into the rpc arg parameter */
2010 
2011         arg.uid = (OM_uint32) uid;
2012 
2013         arg.cred_handle.GSS_CRED_ID_T_len =
2014                         cred_handle == GSSD_NO_CREDENTIAL ?
2015                         0 : (uint_t)sizeof (gssd_cred_id_t);
2016         arg.cred_handle.GSS_CRED_ID_T_val = (char *)&cred_handle;
2017         arg.gssd_cred_verifier = gssd_cred_verifier;
2018 
2019         arg.mech_type.GSS_OID_len =
2020                 (uint_t)(mech_type != GSS_C_NULL_OID ?
2021                 mech_type->length : 0);
2022         arg.mech_type.GSS_OID_val =
2023                 (char *)(mech_type != GSS_C_NULL_OID ?
2024                 mech_type->elements : 0);
2025         /* call the remote procedure */
2026 
2027         memset(&res, 0, sizeof (res));
2028         if (gss_inquire_cred_by_mech_1(&arg, &res, clnt) != RPC_SUCCESS) {
2029 
2030         /*
2031          * if the RPC call times out, null out all return arguments,
2032          * set minor_status to its maximum value, and return GSS_S_FAILURE
2033          */
2034 
2035                 if (minor_status != NULL)
2036                         *minor_status = DEFAULT_MINOR_STAT;
2037                 return (GSS_S_FAILURE);
2038         }
2039 
2040         /* copy the rpc results into the return arguments */
2041 
2042         if (minor_status != NULL)
2043                 *minor_status = res.minor_status;
2044 
2045         /* convert name from external to internal format */
2046 
2047         /*
2048          * free the memory allocated for the results and return with the status
2049          * received in the rpc call
2050          */
2051 
2052         clnt_freeres(clnt, xdr_gss_inquire_cred_by_mech_res, (caddr_t)&res);
2053         return (res.status);
2054 }
2055 
2056 
2057 OM_uint32
2058 kgss_inquire_cred_by_mech(minor_status,
2059                         cred_handle,
2060                         mech_type,
2061                         uid)
2062         OM_uint32 *minor_status;
2063         gss_cred_id_t cred_handle;
2064         gss_OID mech_type;
2065         uid_t uid;
2066 {
2067 
2068         OM_uint32 gssd_cred_verifier;
2069         gssd_cred_id_t gssd_cred_handle;
2070 
2071         gssd_cred_verifier = KCRED_TO_CREDV(cred_handle);
2072         gssd_cred_handle = KCRED_TO_CRED(cred_handle);
2073 
2074         return (kgss_inquire_cred_by_mech_wrapped(minor_status,
2075                         gssd_cred_handle, gssd_cred_verifier,
2076                         mech_type, uid));
2077 }
2078 
2079 OM_uint32
2080 kgsscred_expname_to_unix_cred(expName, uidOut, gidOut, gids, gidsLen, uid)
2081         const gss_buffer_t expName;
2082         uid_t *uidOut;
2083         gid_t *gidOut;
2084         gid_t *gids[];
2085         int *gidsLen;
2086         uid_t uid;
2087 {
2088         gsscred_expname_to_unix_cred_arg args;
2089         gsscred_expname_to_unix_cred_res res;
2090 
2091         /* check input/output parameters */
2092         if (expName == NULL || expName->value == NULL)
2093                 return (GSS_S_CALL_INACCESSIBLE_READ);
2094 
2095         if (uidOut == NULL)
2096                 return (GSS_S_CALL_INACCESSIBLE_WRITE);
2097 
2098         /* NULL out output parameters */
2099         *uidOut = 0;
2100         if (gidsLen)
2101                 *gidsLen = 0;
2102 
2103         if (gids)
2104                 *gids = NULL;
2105 
2106         /* get the client handle to gssd */
2107         if ((clnt = getgssd_handle()) == NULL)
2108         {
2109                 clnt_pcreateerror(server);
2110                 return (GSS_S_FAILURE);
2111         }
2112 
2113         /* copy the procedure arguments */
2114         args.uid = uid;
2115         args.expname.GSS_BUFFER_T_val = expName->value;
2116         args.expname.GSS_BUFFER_T_len = expName->length;
2117 
2118         /* null out the return buffer and call the remote proc */
2119         memset(&res, 0, sizeof (res));
2120 
2121         if (gsscred_expname_to_unix_cred_1(&args, &res, clnt) != RPC_SUCCESS)
2122         {
2123                 return (GSS_S_FAILURE);
2124         }
2125 
2126         /* copy the results into the result parameters */
2127         if (res.major == GSS_S_COMPLETE)
2128         {
2129                 *uidOut = res.uid;
2130                 if (gidOut)
2131                         *gidOut = res.gid;
2132                 if (gids && gidsLen)
2133                 {
2134                         *gids = res.gids.GSSCRED_GIDS_val;
2135                         *gidsLen = res.gids.GSSCRED_GIDS_len;
2136                         res.gids.GSSCRED_GIDS_val = NULL;
2137                         res.gids.GSSCRED_GIDS_len = 0;
2138                 }
2139         }
2140 
2141         /* free RPC results */
2142         clnt_freeres(clnt, xdr_gsscred_expname_to_unix_cred_res, (caddr_t)&res);
2143 
2144         return (res.major);
2145 } /* kgsscred_expname_to_unix_cred */
2146 
2147 OM_uint32
2148 kgsscred_name_to_unix_cred(intName, mechType, uidOut, gidOut, gids,
2149                                 gidsLen, uid)
2150         const gss_name_t intName;
2151         const gss_OID mechType;
2152         uid_t *uidOut;
2153         gid_t *gidOut;
2154         gid_t *gids[];
2155         int *gidsLen;
2156         uid_t uid;
2157 {
2158         gsscred_name_to_unix_cred_arg args;
2159         gsscred_name_to_unix_cred_res res;
2160         OM_uint32 major, minor;
2161         gss_OID nameOid;
2162         gss_buffer_desc flatName = GSS_C_EMPTY_BUFFER;
2163 
2164 
2165         /* check the input/output parameters */
2166         if (intName == NULL || mechType == NULL)
2167                 return (GSS_S_CALL_INACCESSIBLE_READ);
2168 
2169         if (uidOut == NULL)
2170                 return (GSS_S_CALL_INACCESSIBLE_WRITE);
2171 
2172         /* NULL out the output parameters */
2173         *uidOut = 0;
2174         if (gids)
2175                 *gids = NULL;
2176 
2177         if (gidsLen)
2178                 *gidsLen = 0;
2179 
2180         /* get the client handle to gssd */
2181         if ((clnt = getgssd_handle()) == NULL)
2182         {
2183                 clnt_pcreateerror(server);
2184                 return (GSS_S_FAILURE);
2185         }
2186 
2187         /* convert the name to flat representation */
2188         if ((major = gss_display_name(&minor, intName, &flatName, &nameOid))
2189                         != GSS_S_COMPLETE)
2190         {
2191                 return (major);
2192         }
2193 
2194         /* set the rpc parameters */
2195         args.uid = uid;
2196         args.pname.GSS_BUFFER_T_len = flatName.length;
2197         args.pname.GSS_BUFFER_T_val = flatName.value;
2198         args.name_type.GSS_OID_len = nameOid->length;
2199         args.name_type.GSS_OID_val = nameOid->elements;
2200         args.mech_type.GSS_OID_len = mechType->length;
2201         args.mech_type.GSS_OID_val = mechType->elements;
2202 
2203         /* call the remote procedure */
2204         memset(&res, 0, sizeof (res));
2205         if (gsscred_name_to_unix_cred_1(&args, &res, clnt) != RPC_SUCCESS)
2206         {
2207                 gss_release_buffer(&minor, &flatName);
2208                 return (GSS_S_FAILURE);
2209         }
2210 
2211         gss_release_buffer(&minor, &flatName);
2212         /* copy the output parameters on output */
2213         if (res.major == GSS_S_COMPLETE)
2214         {
2215                 *uidOut = res.uid;
2216                 if (gidOut)
2217                         *gidOut = res.gid;
2218                 if (gids && gidsLen)
2219                 {
2220                         *gids = res.gids.GSSCRED_GIDS_val;
2221                         *gidsLen = res.gids.GSSCRED_GIDS_len;
2222                         res.gids.GSSCRED_GIDS_val = NULL;
2223                         res.gids.GSSCRED_GIDS_len = 0;
2224                 }
2225         }
2226 
2227         /* delete RPC allocated memory */
2228         clnt_freeres(clnt, xdr_gsscred_name_to_unix_cred_res, (caddr_t)&res);
2229 
2230         return (res.major);
2231 } /* kgsscred_name_to_unix_cred */
2232 
2233 OM_uint32
2234 kgss_get_group_info(puid, gidOut, gids, gidsLen, uid)
2235         const uid_t puid;
2236         gid_t *gidOut;
2237         gid_t *gids[];
2238         int *gidsLen;
2239         uid_t uid;
2240 {
2241         gss_get_group_info_arg args;
2242         gss_get_group_info_res res;
2243 
2244 
2245         /* check the output parameters */
2246         if (gidOut == NULL || gids == NULL || gidsLen == NULL)
2247                 return (GSS_S_CALL_INACCESSIBLE_WRITE);
2248 
2249         /* get the client GSSD handle */
2250         if ((clnt = getgssd_handle()) == NULL)
2251         {
2252                 clnt_pcreateerror(server);
2253                 return (GSS_S_FAILURE);
2254         }
2255 
2256         /* set the input parameters */
2257         args.uid = uid;
2258         args.puid = puid;
2259 
2260 
2261         /* call the remote procedure */
2262         memset(&res, 0, sizeof (res));
2263         if (gss_get_group_info_1(&args, &res, clnt) != RPC_SUCCESS)
2264         {
2265                 return (GSS_S_FAILURE);
2266         }
2267 
2268         /* copy the results */
2269         if (res.major == GSS_S_COMPLETE)
2270         {
2271                 *gidOut = res.gid;
2272                 *gids = res.gids.GSSCRED_GIDS_val;
2273                 *gidsLen = res.gids.GSSCRED_GIDS_len;
2274                 res.gids.GSSCRED_GIDS_val = NULL;
2275                 res.gids.GSSCRED_GIDS_len = 0;
2276         }
2277 
2278         /* nothing to free */
2279 
2280         return (res.major);
2281 } /* kgss_get_group_info */
2282 
2283 OM_uint32
2284 kgss_export_sec_context_wrapped(minor_status,
2285                                 context_handle,
2286                                 output_token,
2287                                 gssd_context_verifier)
2288         OM_uint32 *minor_status;
2289         gssd_ctx_id_t *context_handle;
2290         gss_buffer_t output_token;
2291         OM_uint32 gssd_context_verifier;
2292 {
2293         CLIENT *clnt;
2294         gss_export_sec_context_arg arg;
2295         gss_export_sec_context_res res;
2296 
2297 
2298 /* get the client handle to GSSD */
2299 
2300         if ((clnt = getgssd_handle()) == NULL) {
2301                 clnt_pcreateerror(server);
2302                 return (GSS_S_FAILURE);
2303         }
2304 
2305 /* copy the procedure arguments into the rpc arg parameter */
2306 
2307         arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
2308         arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle;
2309         arg.gssd_context_verifier = gssd_context_verifier;
2310 
2311 /* call the remote procedure */
2312 
2313         memset(&res, 0, sizeof (res));
2314         if (gss_export_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
2315 
2316 /*
2317  * if the RPC call times out, null out all return arguments, set minor_status
2318  * to its maximum value, and return GSS_S_FAILURE
2319  */
2320 
2321                 if (minor_status != NULL)
2322                         *minor_status = DEFAULT_MINOR_STAT;
2323                 if (context_handle != NULL)
2324                         *context_handle = NULL;
2325                 if (output_token != NULL)
2326                         output_token->length = 0;
2327 
2328                 return (GSS_S_FAILURE);
2329         }
2330 
2331 /* copy the rpc results into the return arguments */
2332 
2333         if (minor_status != NULL)
2334                 *minor_status = res.minor_status;
2335 
2336         if (res.context_handle.GSS_CTX_ID_T_len == 0)
2337                 *context_handle = NULL;
2338         else
2339                 *context_handle =
2340                     *((gssd_ctx_id_t *)res.context_handle.GSS_CTX_ID_T_val);
2341 
2342         if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) {
2343                 output_token->length = res.output_token.GSS_BUFFER_T_len;
2344                 output_token->value =
2345                         (void *) MALLOC(output_token->length);
2346                 memcpy(output_token->value,
2347                         res.output_token.GSS_BUFFER_T_val,
2348                         output_token->length);
2349         }
2350 
2351 /*
2352  * free the memory allocated for the results and return with the status
2353  * received in the rpc call
2354  */
2355 
2356         clnt_freeres(clnt, xdr_gss_export_sec_context_res, (caddr_t)&res);
2357         return (res.status);
2358 
2359 }
2360 
2361 OM_uint32
2362 kgss_export_sec_context(minor_status,
2363                         context_handle,
2364                         output_token)
2365         OM_uint32 *minor_status;
2366         gss_ctx_id_t *context_handle;
2367         gss_buffer_t output_token;
2368 {
2369         OM_uint32 err;
2370         struct kgss_ctx *kctx;
2371 
2372         if (*context_handle == GSS_C_NO_CONTEXT) {
2373                 return (GSS_S_NO_CONTEXT);
2374         } else
2375                 kctx = KCTX_TO_KGSS_CTX(*context_handle);
2376 
2377         err = kgss_export_sec_context_wrapped(minor_status,
2378                 &kctx->gssd_ctx, output_token,
2379                 kctx->gssd_ctx_verifier);
2380 
2381         if (GSS_ERROR(err))
2382                 return (err);
2383         else {
2384                 KGSS_FREE(kctx);
2385                 *context_handle = GSS_C_NO_CONTEXT;
2386                 return (err);
2387         }
2388 
2389 }
2390 
2391 OM_uint32
2392 kgss_import_sec_context_wrapped(minor_status,
2393                         input_token,
2394                         context_handle,
2395                         gssd_context_verifier)
2396         OM_uint32 *minor_status;
2397         gss_buffer_t input_token;
2398         gss_ctx_id_t *context_handle;
2399         OM_uint32 gssd_context_verifier;
2400 {
2401         CLIENT *clnt;
2402         gss_import_sec_context_arg arg;
2403         gss_import_sec_context_res res;
2404 
2405 
2406 /* get the client handle to GSSD */
2407 
2408         if ((clnt = getgssd_handle()) == NULL) {
2409                 clnt_pcreateerror(server);
2410                 return (GSS_S_FAILURE);
2411         }
2412 
2413 /* copy the procedure arguments into the rpc arg parameter */
2414         arg.input_token.GSS_BUFFER_T_len = (uint_t)
2415                 (input_token != GSS_C_NO_BUFFER ? input_token->length : 0);
2416         arg.input_token.GSS_BUFFER_T_val = (char *)
2417                 (input_token != GSS_C_NO_BUFFER ? input_token->value : 0);
2418         arg.gssd_context_verifier = gssd_context_verifier;
2419 
2420 
2421 /* call the remote procedure */
2422 
2423         memset(&res, 0, sizeof (res));
2424         if (gss_import_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
2425 
2426 /*
2427  * if the RPC call times out, null out all return arguments, set minor_status
2428  * to its maximum value, and return GSS_S_FAILURE
2429  */
2430 
2431                 if (minor_status != NULL)
2432                         *minor_status = DEFAULT_MINOR_STAT;
2433                 if (context_handle != NULL)
2434                         *context_handle = NULL;
2435 
2436                 return (GSS_S_FAILURE);
2437         }
2438 
2439 /* copy the rpc results into the return arguments */
2440 
2441         if (minor_status != NULL)
2442                 *minor_status = res.minor_status;
2443 
2444         if (res.context_handle.GSS_CTX_ID_T_len == 0)
2445                 *context_handle = NULL;
2446         else
2447                 *context_handle =
2448                     *((gss_ctx_id_t *)res.context_handle.GSS_CTX_ID_T_val);
2449 
2450 
2451 /*
2452  * free the memory allocated for the results and return with the status
2453  * received in the rpc call
2454  */
2455 
2456         clnt_freeres(clnt, xdr_gss_import_sec_context_res, (caddr_t)&res);
2457         return (res.status);
2458 }
2459 
2460 OM_uint32
2461 kgss_import_sec_context(minor_status,
2462                         input_token,
2463                         context_handle)
2464         OM_uint32 *minor_status;
2465         gss_buffer_t input_token;
2466         gss_ctx_id_t *context_handle;
2467 {
2468         struct kgss_ctx *kctx;
2469 
2470         if (*context_handle == GSS_C_NO_CONTEXT) {
2471                 kctx = KGSS_ALLOC();
2472                 *context_handle = (gss_ctx_id_t)kctx;
2473                 kctx->gssd_ctx = (OM_uint32) GSS_C_NO_CONTEXT;
2474         } else
2475                 kctx = (struct kgss_ctx *)*context_handle;
2476         return (kgss_import_sec_context_wrapped(minor_status,
2477                 input_token, &kctx->gssd_ctx,
2478                 KCTX_TO_CTXV(context_handle)));
2479 }
2480 
2481 #ifdef _KERNEL
2482 #include <sys/modctl.h>
2483 
2484 static void *gss_clnt = NULL;
2485 
2486 #ifdef DEBUG
2487 typedef struct {
2488         char            *name;          /* just put something here */
2489 } gssd_devstate_t;
2490 
2491 
2492 static void *gssd_state;
2493 
2494 static int gssd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2495 {
2496         /*       cmn_err(CE_NOTE, "In gssd_attach"); */
2497         switch (cmd) {
2498         case DDI_ATTACH:
2499                 if (ddi_create_minor_node(dip, "gssd", S_IFCHR, 0, "gssd", 0)
2500                     == DDI_FAILURE) {
2501                         ddi_remove_minor_node(dip, NULL);
2502                         return (DDI_FAILURE);
2503                 }
2504                 return (DDI_SUCCESS);
2505 
2506         default:
2507                 return (DDI_FAILURE);
2508         }
2509 }
2510 
2511 static int gssd_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd,
2512                 void *arg, void **result)
2513 {
2514         dev_t dev;
2515         int error;
2516 
2517 /*       cmn_err(CE_NOTE, "In gssd_getinfo"); */
2518 
2519         switch (infocmd) {
2520         case DDI_INFO_DEVT2INSTANCE:
2521                 dev = (dev_t)arg;
2522                 *result = (void *) getminor(dev);
2523                 error = DDI_SUCCESS;
2524                 break;
2525 
2526         case DDI_INFO_DEVT2DEVINFO:
2527         /*      cmn_err(CE_NOTE, "getinfo wants devinfo"); */
2528         default:
2529                 error = DDI_FAILURE;
2530                 break;
2531         }
2532         return (error);
2533 }
2534 
2535 static int gssd_identify(dev_info_t *dip)
2536 {
2537         /*       cmn_err(CE_NOTE, "in gssd_identify"); */
2538         if (strcmp(ddi_get_name(dip), "gssd") == 0)
2539                 return (DDI_IDENTIFIED);
2540         else
2541                 return (DDI_NOT_IDENTIFIED);
2542 }
2543 
2544 static int gssd_probe(dev_info_t *dip)
2545 {
2546         /*       cmn_err(CE_NOTE, "In gssd_probe"); */
2547 
2548         return (DDI_PROBE_SUCCESS);
2549 }
2550 
2551 static int gssd_open(dev_t *devp, int flag, int otyp, cred_t *credp)
2552 {
2553         /*       cmn_err (CE_NOTE, "In gssd_open"); */
2554         if (otyp != OTYP_CHR)
2555                 return (EINVAL);
2556 
2557         gss_clnt = getgssd_handle();
2558         return (0);
2559 }
2560 
2561 static int gssd_close(dev_t dev, int flag, int otyp, cred_t *credp)
2562 {
2563         /*       cmn_err(CE_NOTE, "In gssd_close"); */
2564         killgssd_handle(gss_clnt);
2565         return (0);
2566 }
2567 
2568 static int gssd_write(dev_t dev, struct uio *uiop, cred_t *credp)
2569 {
2570         char buffer[1024];
2571         int len;
2572 
2573         /*       cmn_err(CE_NOTE, "In gssd_write"); */
2574         bzero(buffer, 1024);
2575 
2576         uiomove(buffer, 1024, UIO_WRITE, uiop);
2577         len = strlen(buffer);
2578 
2579         if (buffer[len-1] == '\n')
2580                 buffer[--len] = '\0';
2581 
2582         cmn_err(CE_NOTE, "Got command: (%d) \"%s\"", len, buffer);
2583         do_gssdtest(buffer);
2584         return (0);
2585 }
2586 
2587 static struct cb_ops gssd_cb_ops = {
2588         gssd_open,              /* cb_open */
2589         gssd_close,             /* cb_close */
2590         nodev,                  /* cb_strategy */
2591         nodev,                  /* cb_print */
2592         nodev,                  /* cb_dump */
2593         nulldev,                /* cb_read */
2594         gssd_write,             /* cb_write */
2595         nodev,                  /* cb_ioctl */
2596         nodev,                  /* cb_devmap */
2597         nodev,                  /* cb_mmap */
2598         nodev,                  /* cb_segmap */
2599         nochpoll,               /* cb_chpoll */
2600         ddi_prop_op,            /* cb_prop_op */
2601         NULL,                   /* cb_stream */
2602         (int)(D_NEW|D_MP)       /* cb_flag */
2603 };
2604 
2605 static struct dev_ops gssd_ops = {
2606         DEVO_REV,               /* devo_rev */
2607         0,                      /* devo_refcnt */
2608         gssd_getinfo,           /* devo_getinfo */
2609         gssd_identify,          /* devo_identify */
2610         nulldev,                /* devo_probe */
2611         gssd_attach,            /* devo_attach */
2612         nulldev,                /* devo_detach */
2613         nodev,                  /* devo_reset */
2614         &gssd_cb_ops,               /* devo_cb_ops */
2615         (struct bus_ops *)NULL  /* devo_bus_ops */
2616 };
2617 
2618 extern struct mod_ops mod_driverops;
2619 
2620 static struct modldrv modlmisc = {
2621         &mod_driverops,
2622         "GSSD DRV Client Module",
2623         &gssd_ops
2624 
2625 #else /* !DEBUG */
2626 
2627 static struct modlmisc modlmisc = {
2628         &mod_miscops,
2629         "GSSD Client Module"
2630 #endif /* DEBUG */
2631 };
2632 
2633 static struct modlinkage modlinkage = {
2634         MODREV_1,
2635         (void *)&modlmisc,
2636         NULL
2637 };
2638 
2639 char _depends_on[] = "strmod/rpcmod misc/tlimod";
2640 
2641 _init(void)
2642 {
2643         int status;
2644 
2645         if ((status = ddi_soft_state_init(&gssd_state,
2646             sizeof (gssd_devstate_t), 1)) != 0)
2647                 return (status);
2648 
2649         if ((status = mod_install((struct modlinkage *)&modlinkage)) != 0)
2650                 ddi_soft_state_fini(&gssd_state);
2651 
2652         cmn_err(CE_NOTE, "gssd: I'm in the kernel: %d.", status);
2653         return (status);
2654 }
2655 
2656 _fini()
2657 {
2658         int status;
2659 
2660         killgssd_handle(gss_clnt);
2661         cmn_err(CE_NOTE, "gssd: Handle destroyed.. leaving module.");
2662 
2663         if ((status = mod_remove(&modlinkage)) != 0)
2664                 return (status);
2665 
2666         ddi_soft_state_fini(&gssd_state);
2667         return (status);
2668 }
2669 
2670 _info(modinfop)
2671 struct modinfo *modinfop;
2672 {
2673         return (mod_info(&modlinkage, modinfop));
2674 }
2675 
2676 #endif