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