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 } 2668