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