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