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