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