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