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