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 /* EXPORT DELETE START */
1910 
1911 bool_t
1912 gss_seal_1_svc(argp, res, rqstp)
1913 gss_seal_arg *argp;
1914 gss_seal_res *res;
1915 struct svc_req *rqstp;
1916 {
1917         uid_t uid;
1918 
1919         gss_buffer_desc input_message_buffer;
1920         gss_buffer_desc output_message_buffer;
1921         gss_ctx_id_t context_handle;
1922         bool_t context_verf_ok;
1923 
1924         memset(res, 0, sizeof (*res));
1925 
1926         if (gssd_debug)
1927                 fprintf(stderr, gettext("gss_seal\n"));
1928 
1929         gssd_convert_context_handle(&argp->context_handle, &context_handle,
1930                 argp->gssd_context_verifier, &context_verf_ok, NULL);
1931 
1932         /* verify the context_handle */
1933 
1934         if (!context_verf_ok) {
1935                 res->output_message_buffer.GSS_BUFFER_T_val = NULL;
1936                 res->output_message_buffer.GSS_BUFFER_T_len = 0;
1937                 res->status = (OM_uint32) GSS_S_NO_CONTEXT;
1938                 res->minor_status = 0;
1939                 return (TRUE);
1940         }
1941 
1942         /*
1943          * if the request isn't from root, null out the result pointer
1944          * entries, so the next time through xdr_free won't try to
1945          * free unmalloc'd memory and then return NULL
1946          */
1947 
1948         if (checkfrom(rqstp, &uid) == 0) {
1949                 res->output_message_buffer.GSS_BUFFER_T_val = NULL;
1950                 return (FALSE);
1951 
1952         }
1953 
1954 
1955         /*
1956          * copy the XDR structured arguments into their corresponding local
1957          * GSSAPI variable equivalents.
1958          */
1959 
1960         input_message_buffer.length = (size_t)argp->input_message_buffer.
1961                                         GSS_BUFFER_T_len;
1962         input_message_buffer.value = (void *)argp->input_message_buffer.
1963                                         GSS_BUFFER_T_val;
1964 
1965 
1966         /* call the gssapi routine */
1967 
1968         res->status = (OM_uint32)gss_seal(&res->minor_status,
1969                                 context_handle,
1970                                 argp->conf_req_flag,
1971                                 argp->qop_req,
1972                                 &input_message_buffer,
1973                                 &res->conf_state,
1974                                 &output_message_buffer);
1975         /*
1976          * convert the output args from the parameter given in the call to the
1977          * variable in the XDR result
1978          */
1979 
1980         if (res->status == GSS_S_COMPLETE) {
1981                 res->output_message_buffer.GSS_BUFFER_T_len =
1982                                 (uint_t)output_message_buffer.length;
1983                 res->output_message_buffer.GSS_BUFFER_T_val =
1984                                 (char *)output_message_buffer.value;
1985         } else
1986                 syslog_gss_error(res->status, res->minor_status, "seal");
1987 
1988 /* return to caller */
1989 
1990         return (TRUE);
1991 }
1992 
1993 bool_t
1994 gss_unseal_1_svc(argp, res, rqstp)
1995 gss_unseal_arg *argp;
1996 gss_unseal_res *res;
1997 struct svc_req *rqstp;
1998 {
1999 
2000         uid_t uid;
2001 
2002         gss_buffer_desc input_message_buffer;
2003         gss_buffer_desc output_message_buffer;
2004         gss_ctx_id_t context_handle;
2005         bool_t context_verf_ok;
2006 
2007         memset(res, 0, sizeof (*res));
2008 
2009         if (gssd_debug)
2010                 fprintf(stderr, gettext("gss_unseal\n"));
2011 
2012         /* verify the context_handle */
2013         gssd_convert_context_handle(&argp->context_handle, &context_handle,
2014                 argp->gssd_context_verifier, &context_verf_ok, NULL);
2015 
2016         /* verify the context_handle */
2017         if (!context_verf_ok) {
2018                 res->output_message_buffer.GSS_BUFFER_T_val = NULL;
2019                 res->output_message_buffer.GSS_BUFFER_T_len = 0;
2020                 res->status = (OM_uint32)GSS_S_NO_CONTEXT;
2021                 res->minor_status = 0;
2022                 return (TRUE);
2023         }
2024 
2025         /*
2026          * if the request isn't from root, null out the result pointer
2027          * entries, so the next time through xdr_free won't try to
2028          * free unmalloc'd memory and then return NULL
2029          */
2030 
2031         if (checkfrom(rqstp, &uid) == 0) {
2032                 res->output_message_buffer.GSS_BUFFER_T_val = NULL;
2033                 return (FALSE);
2034         }
2035 
2036 
2037         /*
2038          * copy the XDR structured arguments into their corresponding local
2039          * GSSAPI variable equivalents.
2040          */
2041 
2042         input_message_buffer.length = (size_t)argp->input_message_buffer.
2043                                         GSS_BUFFER_T_len;
2044         input_message_buffer.value = (void *)argp->input_message_buffer.
2045                                         GSS_BUFFER_T_val;
2046 
2047         /* call the gssapi routine */
2048 
2049         res->status = (OM_uint32)gss_unseal(&res->minor_status,
2050                                 context_handle,
2051                                 &input_message_buffer,
2052                                 &output_message_buffer,
2053                                 &res->conf_state,
2054                                 &res->qop_state);
2055 
2056         /*
2057          * convert the output args from the parameter given in the call to the
2058          * variable in the XDR result
2059          */
2060 
2061         if (res->status == GSS_S_COMPLETE) {
2062                 res->output_message_buffer.GSS_BUFFER_T_len =
2063                                 (uint_t)output_message_buffer.length;
2064                 res->output_message_buffer.GSS_BUFFER_T_val =
2065                                 (char *)output_message_buffer.value;
2066         } else
2067                 syslog_gss_error(res->status, res->minor_status, "unseal");
2068 
2069 
2070         /* return to caller */
2071 
2072         return (TRUE);
2073 }
2074 
2075 /* EXPORT DELETE END */
2076 
2077 bool_t
2078 gss_display_status_1_svc(argp, res, rqstp)
2079 gss_display_status_arg *argp;
2080 gss_display_status_res *res;
2081 struct svc_req *rqstp;
2082 {
2083         uid_t uid;
2084         gss_OID mech_type;
2085         gss_OID_desc mech_type_desc;
2086         gss_buffer_desc status_string;
2087 
2088         memset(res, 0, sizeof (*res));
2089 
2090         if (gssd_debug)
2091                 fprintf(stderr, gettext("gss_display_status\n"));
2092 
2093         /*
2094          * if the request isn't from root, null out the result pointer
2095          * entries, so the next time through xdr_free won't try to
2096          * free unmalloc'd memory and then return NULL
2097          */
2098 
2099         if (checkfrom(rqstp, &uid) == 0) {
2100                 res->status_string.GSS_BUFFER_T_val = NULL;
2101                 return (FALSE);
2102         }
2103 
2104         /* set the uid sent as the RPC argument */
2105 
2106         uid = argp->uid;
2107         set_gssd_uid(uid);
2108 
2109         /*
2110          * copy the XDR structured arguments into their corresponding local
2111          * GSSAPI variables.
2112          */
2113 
2114         if (argp->mech_type.GSS_OID_len == 0)
2115                 mech_type = GSS_C_NULL_OID;
2116         else {
2117                 mech_type = &mech_type_desc;
2118                 mech_type_desc.length = (OM_uint32) argp->mech_type.GSS_OID_len;
2119                 mech_type_desc.elements = (void *) argp->mech_type.GSS_OID_val;
2120         }
2121 
2122 
2123         /* call the gssapi routine */
2124 
2125         res->status = (OM_uint32) gss_display_status(&res->minor_status,
2126                                         argp->status_value,
2127                                         argp->status_type,
2128                                         mech_type,
2129                                         (OM_uint32 *)&res->message_context,
2130                                         &status_string);
2131 
2132         /*
2133          * convert the output args from the parameter given in the call to the
2134          * variable in the XDR result
2135          */
2136 
2137         if (res->status == GSS_S_COMPLETE) {
2138                 res->status_string.GSS_BUFFER_T_len =
2139                         (uint_t)status_string.length;
2140                 res->status_string.GSS_BUFFER_T_val =
2141                         (char *)status_string.value;
2142         }
2143 
2144         return (TRUE);
2145 
2146 }
2147 
2148 /*ARGSUSED*/
2149 bool_t
2150 gss_indicate_mechs_1_svc(argp, res, rqstp)
2151         void *argp;
2152         gss_indicate_mechs_res *res;
2153         struct svc_req *rqstp;
2154 {
2155         gss_OID_set oid_set;
2156         uid_t uid;
2157 
2158         memset(res, 0, sizeof (*res));
2159 
2160         if (gssd_debug)
2161                 fprintf(stderr, gettext("gss_indicate_mechs\n"));
2162 
2163         res->mech_set.GSS_OID_SET_val = NULL;
2164 
2165         /*
2166          * if the request isn't from root, null out the result pointer
2167          * entries, so the next time through xdr_free won't try to
2168          * free unmalloc'd memory and then return NULL
2169          */
2170 
2171         if (checkfrom(rqstp, &uid) == 0) {
2172                 return (FALSE);
2173         }
2174 
2175         res->status = gss_indicate_mechs(&res->minor_status, &oid_set);
2176 
2177         if (res->status == GSS_S_COMPLETE) {
2178                 int i, j;
2179 
2180                 res->mech_set.GSS_OID_SET_len = oid_set->count;
2181                 res->mech_set.GSS_OID_SET_val = (void *)
2182                                 malloc(oid_set->count * sizeof (GSS_OID));
2183                 if (!res->mech_set.GSS_OID_SET_val) {
2184                         return (GSS_S_FAILURE);
2185                 }
2186                 for (i = 0; i < oid_set->count; i++) {
2187                         res->mech_set.GSS_OID_SET_val[i].GSS_OID_len =
2188                                 oid_set->elements[i].length;
2189                         res->mech_set.GSS_OID_SET_val[i].GSS_OID_val =
2190                                 (char *)malloc(oid_set->elements[i].length);
2191                         if (!res->mech_set.GSS_OID_SET_val[i].GSS_OID_val) {
2192                                 for (j = 0; j < (i -1); j++) {
2193                                 free
2194                                 (res->mech_set.GSS_OID_SET_val[i].GSS_OID_val);
2195                                 }
2196                                 free(res->mech_set.GSS_OID_SET_val);
2197                                 return (GSS_S_FAILURE);
2198                         }
2199                         memcpy(res->mech_set.GSS_OID_SET_val[i].GSS_OID_val,
2200                                 oid_set->elements[i].elements,
2201                                 oid_set->elements[i].length);
2202                 }
2203         }
2204 
2205         return (TRUE);
2206 }
2207 
2208 bool_t
2209 gss_inquire_cred_1_svc(argp, res, rqstp)
2210 gss_inquire_cred_arg *argp;
2211 gss_inquire_cred_res *res;
2212 struct svc_req *rqstp;
2213 {
2214 
2215         uid_t uid;
2216 
2217         OM_uint32 minor_status;
2218         gss_cred_id_t cred_handle;
2219         gss_buffer_desc external_name;
2220         gss_OID name_type;
2221         gss_name_t internal_name;
2222         gss_OID_set mechanisms;
2223         int i, j;
2224 
2225         memset(res, 0, sizeof (*res));
2226 
2227         if (gssd_debug)
2228                 fprintf(stderr, gettext("gss_inquire_cred\n"));
2229 
2230         /* verify the verifier_cred_handle */
2231 
2232         if (argp->gssd_cred_verifier != gssd_time_verf) {
2233                 res->name.GSS_BUFFER_T_val = NULL;
2234                 res->name_type.GSS_OID_val = NULL;
2235                 res->mechanisms.GSS_OID_SET_val = NULL;
2236                 res->status = (OM_uint32) GSS_S_DEFECTIVE_CREDENTIAL;
2237                 res->minor_status = 0;
2238                 return (TRUE);
2239         }
2240 
2241         /*
2242          * if the request isn't from root, null out the result pointer
2243          * entries, so the next time through xdr_free won't try to
2244          * free unmalloc'd memory and then return NULL
2245          */
2246 
2247         if (checkfrom(rqstp, &uid) == 0) {
2248                 res->name.GSS_BUFFER_T_val = NULL;
2249                 res->name_type.GSS_OID_val = NULL;
2250                 res->mechanisms.GSS_OID_SET_val = NULL;
2251                 return (FALSE);
2252         }
2253 
2254         /* set the uid sent as the RPC argument */
2255 
2256         uid = argp->uid;
2257         set_gssd_uid(uid);
2258 
2259         cred_handle = (argp->cred_handle.GSS_CRED_ID_T_len == 0 ?
2260                         GSS_C_NO_CREDENTIAL :
2261                         /*LINTED*/
2262                         *((gss_cred_id_t *)argp->cred_handle.
2263                                 GSS_CRED_ID_T_val));
2264 
2265         /* call the gssapi routine */
2266 
2267         res->status = (OM_uint32)gss_inquire_cred(&res->minor_status,
2268                                         cred_handle,
2269                                         &internal_name,
2270                                         &res->lifetime,
2271                                         &res->cred_usage,
2272                                         &mechanisms);
2273 
2274         if (res->status != GSS_S_COMPLETE) {
2275                 syslog_gss_error(res->status, res->minor_status,
2276                                 "inquire_cred");
2277                 return (TRUE);
2278         }
2279 
2280         /* convert the returned name from internal to external format */
2281 
2282         if (gss_display_name(&minor_status, internal_name,
2283                                 &external_name, &name_type)
2284                         != GSS_S_COMPLETE) {
2285 
2286                 res->status = (OM_uint32)GSS_S_FAILURE;
2287                 res->minor_status = minor_status;
2288 
2289                 gss_release_name(&minor_status, &internal_name);
2290 
2291                 if (mechanisms != GSS_C_NULL_OID_SET) {
2292                         for (i = 0; i < mechanisms->count; i++)
2293                                 free(mechanisms->elements[i].elements);
2294                         free(mechanisms->elements);
2295                         free(mechanisms);
2296                 }
2297 
2298                 return (TRUE);
2299         }
2300 
2301         /*
2302          * convert the output args from the parameter given in the call to the
2303          * variable in the XDR result
2304          */
2305 
2306 
2307         res->name.GSS_BUFFER_T_len = (uint_t)external_name.length;
2308         res->name.GSS_BUFFER_T_val = (void *)external_name.value;
2309 
2310         /*
2311          * we have to allocate storage for name_type here, since the value
2312          * returned from gss_display_name points to the underlying mechanism
2313          * static storage. If we didn't allocate storage, the next time
2314          * through this routine, the xdr_free() call at the beginning would
2315          * try to free up that static storage.
2316          */
2317 
2318         res->name_type.GSS_OID_len = (uint_t)name_type->length;
2319         res->name_type.GSS_OID_val = (void *)malloc(name_type->length);
2320         if (!res->name_type.GSS_OID_val) {
2321                 return (GSS_S_FAILURE);
2322         }
2323         memcpy(res->name_type.GSS_OID_val, name_type->elements,
2324                 name_type->length);
2325 
2326         if (mechanisms != GSS_C_NULL_OID_SET) {
2327                 res->mechanisms.GSS_OID_SET_len =
2328                         (uint_t)mechanisms->count;
2329                 res->mechanisms.GSS_OID_SET_val = (GSS_OID *)
2330                                 malloc(sizeof (GSS_OID) * mechanisms->count);
2331                 if (!res->mechanisms.GSS_OID_SET_val) {
2332                         free(res->name_type.GSS_OID_val);
2333                         return (GSS_S_FAILURE);
2334                 }
2335                 for (i = 0; i < mechanisms->count; i++) {
2336                         res->mechanisms.GSS_OID_SET_val[i].GSS_OID_len =
2337                                 (uint_t)mechanisms->elements[i].length;
2338                         res->mechanisms.GSS_OID_SET_val[i].GSS_OID_val =
2339                                 (char *)malloc(mechanisms->elements[i].
2340                                                 length);
2341                         if (!res->mechanisms.GSS_OID_SET_val[i].GSS_OID_val) {
2342                                 free(res->name_type.GSS_OID_val);
2343                                 for (j = 0; j < i; j++) {
2344                                 free(res->mechanisms.
2345                                         GSS_OID_SET_val[i].GSS_OID_val);
2346                                 }
2347                                 free(res->mechanisms.GSS_OID_SET_val);
2348                                 return (GSS_S_FAILURE);
2349                         }
2350                         memcpy(res->mechanisms.GSS_OID_SET_val[i].GSS_OID_val,
2351                                 mechanisms->elements[i].elements,
2352                                 mechanisms->elements[i].length);
2353                 }
2354         } else
2355                 res->mechanisms.GSS_OID_SET_len = 0;
2356 
2357         /* release the space allocated for internal_name and mechanisms */
2358         gss_release_name(&minor_status, &internal_name);
2359 
2360         if (mechanisms != GSS_C_NULL_OID_SET) {
2361                 for (i = 0; i < mechanisms->count; i++)
2362                         free(mechanisms->elements[i].elements);
2363                 free(mechanisms->elements);
2364                 free(mechanisms);
2365         }
2366 
2367         /* return to caller */
2368         return (TRUE);
2369 }
2370 
2371 
2372 bool_t
2373 gss_inquire_cred_by_mech_1_svc(argp, res, rqstp)
2374 gss_inquire_cred_by_mech_arg *argp;
2375 gss_inquire_cred_by_mech_res *res;
2376 struct svc_req *rqstp;
2377 {
2378 
2379         uid_t uid;
2380 
2381         gss_cred_id_t cred_handle;
2382         gss_OID_desc            mech_type_desc;
2383         gss_OID                 mech_type = &mech_type_desc;
2384 
2385         memset(res, 0, sizeof (*res));
2386 
2387         if (gssd_debug)
2388                 fprintf(stderr, gettext("gss_inquire_cred\n"));
2389 
2390         /* verify the verifier_cred_handle */
2391 
2392         if (argp->gssd_cred_verifier != gssd_time_verf) {
2393                 res->status = (OM_uint32) GSS_S_DEFECTIVE_CREDENTIAL;
2394                 res->minor_status = 0;
2395                 return (TRUE);
2396         }
2397 
2398         /*
2399          * if the request isn't from root, null out the result pointer
2400          * entries, so the next time through xdr_free won't try to
2401          * free unmalloc'd memory and then return NULL
2402          */
2403 
2404         if (checkfrom(rqstp, &uid) == 0) {
2405                 return (FALSE);
2406         }
2407 
2408         /* set the uid sent as the RPC argument */
2409 
2410         uid = argp->uid;
2411         set_gssd_uid(uid);
2412 
2413         cred_handle = (argp->cred_handle.GSS_CRED_ID_T_len == 0 ?
2414                         GSS_C_NO_CREDENTIAL :
2415                         /*LINTED*/
2416                         *((gss_cred_id_t *)argp->cred_handle.
2417                                 GSS_CRED_ID_T_val));
2418 
2419         /* call the gssapi routine */
2420 
2421         if (argp->mech_type.GSS_OID_len == 0)
2422                 mech_type = GSS_C_NULL_OID;
2423         else {
2424                 mech_type->length =
2425                         (OM_uint32)argp->mech_type.GSS_OID_len;
2426                 mech_type->elements =
2427                         (void *)malloc(mech_type->length);
2428                 if (!mech_type->elements) {
2429                         return (GSS_S_FAILURE);
2430                 }
2431                 memcpy(mech_type->elements,
2432                         argp->mech_type.GSS_OID_val,
2433                         mech_type->length);
2434         }
2435         res->status = (OM_uint32)gss_inquire_cred_by_mech(
2436                                         &res->minor_status, cred_handle,
2437                                         mech_type, NULL, NULL,
2438                                         NULL, NULL);
2439 
2440         /* return to caller */
2441         return (TRUE);
2442 }
2443 
2444 
2445 bool_t
2446 gsscred_name_to_unix_cred_1_svc(argsp, res, rqstp)
2447 gsscred_name_to_unix_cred_arg *argsp;
2448 gsscred_name_to_unix_cred_res *res;
2449 struct svc_req *rqstp;
2450 {
2451         uid_t uid;
2452         gss_OID_desc oid;
2453         gss_name_t gssName;
2454         gss_buffer_desc gssBuf = GSS_C_EMPTY_BUFFER;
2455         OM_uint32 minor;
2456         int gidsLen;
2457         gid_t *gids, gidOut;
2458 
2459         if (gssd_debug)
2460                 fprintf(stderr, gettext("gsscred_name_to_unix_cred\n"));
2461 
2462         memset(res, 0, sizeof (*res));
2463 
2464         /*
2465          * check the request originator
2466          */
2467         if (checkfrom(rqstp, &uid) == 0)
2468                 return (FALSE);
2469 
2470         /* set the uid from the rpc request */
2471         uid = argsp->uid;
2472         set_gssd_uid(uid);
2473 
2474         /*
2475          * convert the principal name to gss internal format
2476          * need not malloc the input parameters
2477          */
2478         gssBuf.length = argsp->pname.GSS_BUFFER_T_len;
2479         gssBuf.value = (void*)argsp->pname.GSS_BUFFER_T_val;
2480         oid.length = argsp->name_type.GSS_OID_len;
2481         oid.elements = (void*)argsp->name_type.GSS_OID_val;
2482 
2483         res->major = gss_import_name(&minor, &gssBuf, &oid, &gssName);
2484         if (res->major != GSS_S_COMPLETE)
2485                 return (TRUE);
2486 
2487         /* retrieve the mechanism type from the arguments */
2488         oid.length = argsp->mech_type.GSS_OID_len;
2489         oid.elements = (void*)argsp->mech_type.GSS_OID_val;
2490 
2491         /* call the gss extensions to map the principal name to unix creds */
2492         res->major = gsscred_name_to_unix_cred(gssName, &oid, &uid, &gidOut,
2493                                         &gids, &gidsLen);
2494         gss_release_name(&minor, &gssName);
2495 
2496         if (res->major == GSS_S_COMPLETE) {
2497                 res->uid = uid;
2498                 res->gid = gidOut;
2499                 res->gids.GSSCRED_GIDS_val = gids;
2500                 res->gids.GSSCRED_GIDS_len = gidsLen;
2501         }
2502 
2503         return (TRUE);
2504 } /* gsscred_name_to_unix_cred_svc_1 */
2505 
2506 bool_t
2507 gsscred_expname_to_unix_cred_1_svc(argsp, res, rqstp)
2508 gsscred_expname_to_unix_cred_arg *argsp;
2509 gsscred_expname_to_unix_cred_res *res;
2510 struct svc_req *rqstp;
2511 {
2512         uid_t uid;
2513         gss_buffer_desc expName = GSS_C_EMPTY_BUFFER;
2514         int gidsLen;
2515         gid_t *gids, gidOut;
2516 
2517         if (gssd_debug)
2518                 fprintf(stderr, gettext("gsscred_expname_to_unix_cred\n"));
2519 
2520         memset(res, 0, sizeof (*res));
2521 
2522         /*
2523          * check the request originator
2524          */
2525         if (checkfrom(rqstp, &uid) == 0)
2526                 return (FALSE);
2527 
2528         /* set the uid from the rpc request */
2529         uid = argsp->uid;
2530         set_gssd_uid(uid);
2531 
2532         /*
2533          * extract the export name from arguments
2534          * need not malloc the input parameters
2535          */
2536         expName.length = argsp->expname.GSS_BUFFER_T_len;
2537         expName.value = (void*)argsp->expname.GSS_BUFFER_T_val;
2538 
2539         res->major = gsscred_expname_to_unix_cred(&expName, &uid,
2540                                         &gidOut, &gids, &gidsLen);
2541 
2542         if (res->major == GSS_S_COMPLETE) {
2543                 res->uid = uid;
2544                 res->gid = gidOut;
2545                 res->gids.GSSCRED_GIDS_val = gids;
2546                 res->gids.GSSCRED_GIDS_len = gidsLen;
2547         }
2548 
2549         return (TRUE);
2550 } /* gsscred_expname_to_unix_cred_1_svc */
2551 
2552 bool_t
2553 gss_get_group_info_1_svc(argsp, res, rqstp)
2554 gss_get_group_info_arg *argsp;
2555 gss_get_group_info_res *res;
2556 struct svc_req *rqstp;
2557 {
2558         uid_t uid;
2559         int gidsLen;
2560         gid_t *gids, gidOut;
2561 
2562         if (gssd_debug)
2563                 fprintf(stderr, gettext("gss_get_group_info\n"));
2564 
2565         memset(res, 0, sizeof (*res));
2566 
2567         /*
2568          * check the request originator
2569          */
2570         if (checkfrom(rqstp, &uid) == 0)
2571                 return (FALSE);
2572 
2573         /* set the uid from the rpc request */
2574         uid = argsp->uid;
2575         set_gssd_uid(uid);
2576 
2577         /*
2578          * extract the uid from the arguments
2579          */
2580         uid = argsp->puid;
2581         res->major = gss_get_group_info(uid, &gidOut, &gids, &gidsLen);
2582         if (res->major == GSS_S_COMPLETE) {
2583                 res->gid = gidOut;
2584                 res->gids.GSSCRED_GIDS_val = gids;
2585                 res->gids.GSSCRED_GIDS_len = gidsLen;
2586         }
2587 
2588         return (TRUE);
2589 } /* gss_get_group_info_1_svc */
2590 
2591 /*ARGSUSED*/
2592 bool_t
2593 gss_get_kmod_1_svc(argsp, res, rqstp)
2594         gss_get_kmod_arg *argsp;
2595         gss_get_kmod_res *res;
2596         struct svc_req *rqstp;
2597 {
2598         gss_OID_desc oid;
2599         char *kmodName;
2600 
2601         if (gssd_debug)
2602                 fprintf(stderr, gettext("gss_get_kmod\n"));
2603 
2604         res->module_follow = FALSE;
2605         oid.length = argsp->mech_oid.GSS_OID_len;
2606         oid.elements = (void *)argsp->mech_oid.GSS_OID_val;
2607         kmodName = __gss_get_kmodName(&oid);
2608 
2609         if (kmodName != NULL) {
2610                 res->module_follow = TRUE;
2611                 res->gss_get_kmod_res_u.modname = kmodName;
2612         }
2613 
2614         return (TRUE);
2615 }
2616 
2617 /*
2618  *  Returns 1 if caller is ok, else 0.
2619  *  If caller ok, the uid is returned in uidp.
2620  */
2621 static int
2622 checkfrom(rqstp, uidp)
2623 struct svc_req *rqstp;
2624 uid_t *uidp;
2625 {
2626         SVCXPRT *xprt = rqstp->rq_xprt;
2627         struct authunix_parms *aup;
2628         uid_t uid;
2629 
2630         /* check client agent uid to ensure it is privileged */
2631         if (__rpc_get_local_uid(xprt, &uid) < 0) {
2632                 syslog(LOG_ERR, gettext("__rpc_get_local_uid failed %s %s"),
2633                         xprt->xp_netid, xprt->xp_tp);
2634                 goto weakauth;
2635         }
2636         if (gssd_debug)
2637                 fprintf(stderr, gettext("checkfrom: local_uid  %d\n"), uid);
2638         if (uid != 0) {
2639                 syslog(LOG_ERR,
2640                         gettext("checkfrom: caller (uid %d) not privileged"),
2641                         uid);
2642                 goto weakauth;
2643         }
2644 
2645         /*
2646          *  Request came from local privileged process.
2647          *  Proceed to get uid of client if needed by caller.
2648          */
2649         if (uidp) {
2650                 if (rqstp->rq_cred.oa_flavor != AUTH_SYS) {
2651                 syslog(LOG_ERR, gettext("checkfrom: not UNIX credentials"));
2652                         goto weakauth;
2653                 }
2654                 /*LINTED*/
2655                 aup = (struct authunix_parms *)rqstp->rq_clntcred;
2656                 *uidp = aup->aup_uid;
2657                 if (gssd_debug) {
2658                         fprintf(stderr,
2659                                 gettext("checkfrom: caller's uid %d\n"), *uidp);
2660                 }
2661         }
2662         return (1);
2663 
2664         weakauth:
2665         svcerr_weakauth(xprt);
2666         return (0);
2667 }