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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * RPC server procedures for the gssapi usermode daemon gssd. 31 */ 32 33 #include <stdio.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 } 107 108 gssd_ctx_slot_tbl = (struct gssd_ctx_slot *) 109 malloc(sizeof (struct gssd_ctx_slot) * max_contexts); 110 111 if (gssd_ctx_slot_tbl == NULL) { 112 (void) fprintf(stderr, 113 gettext("[%s] could not allocate %d byte context table" 114 "\n"), arg, 115 (sizeof (struct gssd_ctx_slot) * max_contexts)); 116 exit(1); 117 } 118 119 for (i = 1; i < max_contexts; i++) { 120 gssd_ctx_slot_tbl[i-1].lru_next = &gssd_ctx_slot_tbl[i]; 121 gssd_ctx_slot_tbl[i].lru_prev = &gssd_ctx_slot_tbl[i-1]; 122 gssd_ctx_slot_tbl[i].inuse = FALSE; 123 gssd_ctx_slot_tbl[i].verf = 0; 124 gssd_ctx_slot_tbl[i].create_time = 0; 125 gssd_ctx_slot_tbl[i].rpcctx = (gss_ctx_id_t)(i + 1); 126 } 127 128 gssd_ctx_slot_tbl[max_contexts - 1].lru_next = &gssd_ctx_slot_tbl[0]; 129 gssd_ctx_slot_tbl[0].lru_prev = &gssd_ctx_slot_tbl[max_contexts - 1]; 130 gssd_ctx_slot_tbl[0].inuse = FALSE; 131 gssd_ctx_slot_tbl[0].verf = 0; 132 gssd_ctx_slot_tbl[0].create_time = 0; 133 gssd_ctx_slot_tbl[0].rpcctx = (gss_ctx_id_t)1; 134 135 gssd_lru_head = &gssd_ctx_slot_tbl[0]; 136 } 137 138 static OM_uint32 syslog_interval = 60; 139 140 static struct gssd_ctx_slot * 141 gssd_alloc_slot(gss_ctx_id_t ctx) 142 { 143 struct gssd_ctx_slot *lru; 144 OM_uint32 current_time; 145 static OM_uint32 last_syslog = 0; 146 static bool_t first_take = TRUE; 147 static int tooks; 148 OM_uint32 minor_status; 149 150 lru = gssd_lru_head; 151 gssd_lru_head = lru->lru_next; 152 153 current_time = (OM_uint32) time(NULL); 154 155 if (last_syslog == 0) 156 last_syslog = current_time; /* Save 1st alloc time */ 157 158 if (lru->inuse) { 159 if (lru->ctx != GSS_C_NO_CONTEXT) 160 (void) gss_delete_sec_context(&minor_status, 161 &lru->ctx, NULL); 162 tooks++; 163 164 if (((current_time - last_syslog) > syslog_interval) || 165 first_take) { 166 syslog(LOG_WARNING, gettext("re-used an existing " 167 "context slot of age %u seconds (%d slots re-" 168 "used during last %u seconds)"), 169 current_time - lru->create_time, tooks, 170 current_time - last_syslog); 171 172 last_syslog = current_time; 173 tooks = 0; 174 first_take = FALSE; 175 } 176 } 177 178 /* 179 * Assign the next context verifier to the context (avoiding zero). 180 */ 181 context_verf++; 182 if (context_verf == 0) 183 context_verf = 1; 184 lru->verf = context_verf; 185 186 lru->create_time = current_time; 187 lru->ctx = ctx; 188 lru->inuse = TRUE; 189 return (lru); 190 } 191 192 /* 193 * We always add 1 because we don't want slot 0 to be confused 194 * with GSS_C_NO_CONTEXT. 195 */ 196 197 static struct gssd_ctx_slot * 198 gssd_handle_to_slot(GSS_CTX_ID_T *h) 199 { 200 intptr_t i; 201 202 if (h->GSS_CTX_ID_T_len == 0) { 203 return (NULL); 204 } 205 if (h->GSS_CTX_ID_T_len != sizeof (i)) 206 return (NULL); 207 208 i = (*(intptr_t *)(h->GSS_CTX_ID_T_val)) - 1; 209 210 if (i < 0 || i >= max_contexts) 211 return (NULL); 212 213 return (&gssd_ctx_slot_tbl[i]); 214 } 215 216 static void 217 gssd_rel_slot(struct gssd_ctx_slot *lru) 218 { 219 struct gssd_ctx_slot *prev, *next; 220 221 if (lru == NULL) 222 return; 223 224 lru->inuse = FALSE; 225 226 /* 227 * Remove entry from its current location in list 228 */ 229 prev = lru->lru_prev; 230 next = lru->lru_next; 231 prev->lru_next = next; 232 next->lru_prev = prev; 233 234 /* 235 * Since it is no longer in use, it is the least recently 236 * used. 237 */ 238 prev = gssd_lru_head->lru_prev; 239 next = gssd_lru_head; 240 241 prev->lru_next = lru; 242 lru->lru_prev = prev; 243 244 next->lru_prev = lru; 245 lru->lru_next = next; 246 247 gssd_lru_head = lru; 248 } 249 250 static void 251 gssd_convert_context_handle(GSS_CTX_ID_T *h, 252 gss_ctx_id_t *context_handle, 253 OM_uint32 verf, 254 bool_t *context_verf_ok, 255 struct gssd_ctx_slot **slotp) 256 { 257 struct gssd_ctx_slot *slot; 258 259 *context_verf_ok = FALSE; 260 *context_handle = (gss_ctx_id_t)1; 261 if (slotp != NULL) 262 *slotp = NULL; 263 264 if (h->GSS_CTX_ID_T_len == 0) { 265 *context_handle = GSS_C_NO_CONTEXT; 266 *context_verf_ok = TRUE; 267 return; 268 } 269 270 slot = gssd_handle_to_slot(h); 271 272 if (slot == NULL) 273 return; 274 275 if (verf != slot->verf) 276 return; 277 278 *context_verf_ok = TRUE; 279 *context_handle = slot->ctx; 280 if (slotp != NULL) 281 *slotp = slot; 282 } 283 284 bool_t 285 gss_acquire_cred_1_svc(argp, res, rqstp) 286 gss_acquire_cred_arg *argp; 287 gss_acquire_cred_res *res; 288 struct svc_req *rqstp; 289 { 290 OM_uint32 minor_status; 291 gss_name_t desired_name; 292 gss_OID_desc name_type_desc; 293 gss_OID name_type = &name_type_desc; 294 OM_uint32 time_req; 295 gss_OID_set_desc desired_mechs_desc; 296 gss_OID_set desired_mechs; 297 int cred_usage; 298 gss_cred_id_t output_cred_handle; 299 gss_OID_set actual_mechs; 300 gss_buffer_desc external_name; 301 uid_t uid; 302 int i, j; 303 304 if (gssd_debug) 305 fprintf(stderr, gettext("gss_acquire_cred\n")); 306 307 memset(res, 0, sizeof (*res)); 308 309 /* 310 * if the request isn't from root, null out the result pointer 311 * entries, so the next time through xdr_free won't try to 312 * free unmalloc'd memory and then return NULL 313 */ 314 315 if (checkfrom(rqstp, &uid) == 0) { 316 res->output_cred_handle.GSS_CRED_ID_T_val = NULL; 317 res->actual_mechs.GSS_OID_SET_val = NULL; 318 return (FALSE); 319 } 320 321 /* set the uid sent as the RPC argument */ 322 323 uid = argp->uid; 324 set_gssd_uid(uid); 325 326 /* convert the desired name from external to internal format */ 327 328 external_name.length = argp->desired_name.GSS_BUFFER_T_len; 329 external_name.value = (void *)malloc(external_name.length); 330 if (!external_name.value) 331 return (GSS_S_FAILURE); 332 memcpy(external_name.value, argp->desired_name.GSS_BUFFER_T_val, 333 external_name.length); 334 335 if (argp->name_type.GSS_OID_len == 0) { 336 name_type = GSS_C_NULL_OID; 337 } else { 338 name_type->length = argp->name_type.GSS_OID_len; 339 name_type->elements = (void *)malloc(name_type->length); 340 if (!name_type->elements) { 341 free(external_name.value); 342 return (GSS_S_FAILURE); 343 } 344 memcpy(name_type->elements, argp->name_type.GSS_OID_val, 345 name_type->length); 346 } 347 348 if (gss_import_name(&minor_status, &external_name, name_type, 349 &desired_name) != GSS_S_COMPLETE) { 350 351 res->status = (OM_uint32) GSS_S_FAILURE; 352 res->minor_status = minor_status; 353 354 free(external_name.value); 355 if (name_type != GSS_C_NULL_OID) 356 free(name_type->elements); 357 358 return (TRUE); 359 } 360 361 /* 362 * copy the XDR structured arguments into their corresponding local GSSAPI 363 * variables. 364 */ 365 366 cred_usage = argp->cred_usage; 367 time_req = argp->time_req; 368 369 if (argp->desired_mechs.GSS_OID_SET_len != 0) { 370 desired_mechs = &desired_mechs_desc; 371 desired_mechs->count = 372 (int)argp->desired_mechs.GSS_OID_SET_len; 373 desired_mechs->elements = (gss_OID) 374 malloc(sizeof (gss_OID_desc) * desired_mechs->count); 375 if (!desired_mechs->elements) { 376 free(external_name.value); 377 free(name_type->elements); 378 return (GSS_S_FAILURE); 379 } 380 for (i = 0; i < desired_mechs->count; i++) { 381 desired_mechs->elements[i].length = 382 (OM_uint32)argp->desired_mechs. 383 GSS_OID_SET_val[i].GSS_OID_len; 384 desired_mechs->elements[i].elements = 385 (void *)malloc(desired_mechs->elements[i]. 386 length); 387 if (!desired_mechs->elements[i].elements) { 388 free(external_name.value); 389 free(name_type->elements); 390 for (j = 0; j < (i -1); j++) { 391 free 392 (desired_mechs->elements[j].elements); 393 } 394 free(desired_mechs->elements); 395 return (GSS_S_FAILURE); 396 } 397 memcpy(desired_mechs->elements[i].elements, 398 argp->desired_mechs.GSS_OID_SET_val[i]. 399 GSS_OID_val, 400 desired_mechs->elements[i].length); 401 } 402 } else 403 desired_mechs = GSS_C_NULL_OID_SET; 404 405 /* call the gssapi routine */ 406 407 res->status = (OM_uint32)gss_acquire_cred(&res->minor_status, 408 desired_name, 409 time_req, 410 desired_mechs, 411 cred_usage, 412 &output_cred_handle, 413 &actual_mechs, 414 &res->time_rec); 415 416 /* 417 * convert the output args from the parameter given in the call to the 418 * variable in the XDR result 419 */ 420 421 res->output_cred_handle.GSS_CRED_ID_T_len = sizeof (gss_cred_id_t); 422 res->output_cred_handle.GSS_CRED_ID_T_val = 423 (void *)malloc(sizeof (gss_cred_id_t)); 424 if (!res->output_cred_handle.GSS_CRED_ID_T_val) { 425 free(external_name.value); 426 free(name_type->elements); 427 for (i = 0; i < desired_mechs->count; i++) { 428 free(desired_mechs->elements[i].elements); 429 } 430 free(desired_mechs->elements); 431 return (GSS_S_FAILURE); 432 } 433 memcpy(res->output_cred_handle.GSS_CRED_ID_T_val, &output_cred_handle, 434 sizeof (gss_cred_id_t)); 435 436 if (actual_mechs != GSS_C_NULL_OID_SET) { 437 res->actual_mechs.GSS_OID_SET_len = 438 (uint_t)actual_mechs->count; 439 res->actual_mechs.GSS_OID_SET_val = (GSS_OID *) 440 malloc(sizeof (GSS_OID) * actual_mechs->count); 441 if (!res->actual_mechs.GSS_OID_SET_val) { 442 free(external_name.value); 443 free(name_type->elements); 444 for (i = 0; i < desired_mechs->count; i++) { 445 free(desired_mechs->elements[i].elements); 446 } 447 free(desired_mechs->elements); 448 free(res->output_cred_handle.GSS_CRED_ID_T_val); 449 return (GSS_S_FAILURE); 450 } 451 for (i = 0; i < actual_mechs->count; i++) { 452 res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_len = 453 (uint_t)actual_mechs->elements[i].length; 454 res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val = 455 (char *)malloc(actual_mechs->elements[i]. 456 length); 457 if (!res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val) { 458 free(external_name.value); 459 free(name_type->elements); 460 free(desired_mechs->elements); 461 for (j = 0; j < desired_mechs->count; j++) { 462 free 463 (desired_mechs->elements[i].elements); 464 } 465 free(res->actual_mechs.GSS_OID_SET_val); 466 for (j = 0; j < (i - 1); j++) { 467 free 468 (res->actual_mechs. 469 GSS_OID_SET_val[j].GSS_OID_val); 470 } 471 return (GSS_S_FAILURE); 472 } 473 memcpy(res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val, 474 actual_mechs->elements[i].elements, 475 actual_mechs->elements[i].length); 476 } 477 } else 478 res->actual_mechs.GSS_OID_SET_len = 0; 479 480 /* 481 * set the time verifier for credential handle. To ensure that the 482 * timestamp is not the same as previous gssd process, verify that 483 * time is not the same as set earlier at start of process. If it 484 * is, sleep one second and reset. (due to one second granularity) 485 */ 486 487 if (res->status == GSS_S_COMPLETE) { 488 res->gssd_cred_verifier = (OM_uint32)time(NULL); 489 if (res->gssd_cred_verifier == gssd_time_verf) { 490 sleep(1); 491 gssd_time_verf = (OM_uint32)time(NULL); 492 } 493 res->gssd_cred_verifier = gssd_time_verf; 494 } 495 496 /* 497 * now release the space allocated by the underlying gssapi mechanism 498 * library for actual_mechs as well as by this routine for 499 * external_name, name_type and desired_name 500 */ 501 502 free(external_name.value); 503 if (name_type != GSS_C_NULL_OID) 504 free(name_type->elements); 505 gss_release_name(&minor_status, &desired_name); 506 507 if (actual_mechs != GSS_C_NULL_OID_SET) { 508 for (i = 0; i < actual_mechs->count; i++) 509 free(actual_mechs->elements[i].elements); 510 free(actual_mechs->elements); 511 free(actual_mechs); 512 } 513 514 if (desired_mechs != GSS_C_NULL_OID_SET) { 515 for (i = 0; i < desired_mechs->count; i++) 516 free(desired_mechs->elements[i].elements); 517 free(desired_mechs->elements); 518 519 } 520 521 /* return to caller */ 522 523 return (TRUE); 524 } 525 526 bool_t 527 gss_add_cred_1_svc(argp, res, rqstp) 528 gss_add_cred_arg *argp; 529 gss_add_cred_res *res; 530 struct svc_req *rqstp; 531 { 532 533 OM_uint32 minor_status; 534 gss_name_t desired_name; 535 gss_OID_desc name_type_desc; 536 gss_OID name_type = &name_type_desc; 537 gss_OID_desc desired_mech_type_desc; 538 gss_OID desired_mech_type = &desired_mech_type_desc; 539 int cred_usage; 540 gss_cred_id_t input_cred_handle; 541 gss_OID_set actual_mechs; 542 gss_buffer_desc external_name; 543 uid_t uid; 544 int i, j; 545 546 if (gssd_debug) 547 fprintf(stderr, gettext("gss_add_cred\n")); 548 549 if (argp->gssd_cred_verifier != gssd_time_verf) { 550 res->status = (OM_uint32)GSS_S_DEFECTIVE_CREDENTIAL; 551 res->minor_status = 0; 552 res->actual_mechs.GSS_OID_SET_len = 0; 553 res->actual_mechs.GSS_OID_SET_val = NULL; 554 res->initiator_time_rec = 0; 555 res->acceptor_time_rec = 0; 556 fprintf(stderr, gettext("gss_add_cred defective cred\n")); 557 return (TRUE); 558 } 559 memset(res, 0, sizeof (*res)); 560 561 /* 562 * if the request isn't from root, null out the result pointer 563 * entries, so the next time through xdr_free won't try to 564 * free unmalloc'd memory and then return NULL 565 */ 566 567 if (checkfrom(rqstp, &uid) == 0) { 568 return (FALSE); 569 } 570 571 /* set the uid sent as the RPC argument */ 572 573 uid = argp->uid; 574 set_gssd_uid(uid); 575 576 /* convert the desired name from external to internal format */ 577 578 external_name.length = argp->desired_name.GSS_BUFFER_T_len; 579 external_name.value = (void *)argp->desired_name.GSS_BUFFER_T_val; 580 name_type->length = argp->name_type.GSS_OID_len; 581 name_type->elements = (void *)argp->name_type.GSS_OID_val; 582 583 if (gss_import_name(&minor_status, &external_name, name_type, 584 &desired_name) != GSS_S_COMPLETE) { 585 586 if (gssd_debug) 587 fprintf(stderr, 588 gettext("gss_add_cred:import name"), 589 gettext(" failed status %d \n"), 590 res->status); 591 res->status = (OM_uint32)GSS_S_FAILURE; 592 res->minor_status = minor_status; 593 return (TRUE); 594 } 595 596 /* 597 * copy the XDR structured arguments into their corresponding local GSSAPI 598 * variables. 599 */ 600 601 cred_usage = argp->cred_usage; 602 if (argp->desired_mech_type.GSS_OID_len == 0) 603 desired_mech_type = GSS_C_NULL_OID; 604 else { 605 desired_mech_type->length = 606 (OM_uint32)argp->desired_mech_type.GSS_OID_len; 607 desired_mech_type->elements = 608 (void *)malloc(desired_mech_type->length); 609 if (!desired_mech_type->elements) { 610 return (GSS_S_FAILURE); 611 } 612 memcpy(desired_mech_type->elements, 613 argp->desired_mech_type.GSS_OID_val, 614 desired_mech_type->length); 615 } 616 input_cred_handle = 617 (argp->input_cred_handle.GSS_CRED_ID_T_len == 0 ? 618 GSS_C_NO_CREDENTIAL : 619 /*LINTED*/ 620 *((gss_cred_id_t *)argp->input_cred_handle. 621 GSS_CRED_ID_T_val)); 622 623 if (input_cred_handle != GSS_C_NO_CREDENTIAL) 624 /* verify the input_cred_handle */ 625 if (argp->gssd_cred_verifier != gssd_time_verf) { 626 res->status = (OM_uint32)GSS_S_DEFECTIVE_CREDENTIAL; 627 res->minor_status = 0; 628 return (TRUE); 629 } 630 631 /* call the gssapi routine */ 632 633 res->status = (OM_uint32)gss_add_cred(&res->minor_status, 634 input_cred_handle, 635 desired_name, 636 desired_mech_type, 637 cred_usage, 638 argp->initiator_time_req, 639 argp->acceptor_time_req, 640 NULL, 641 &actual_mechs, 642 &res->initiator_time_rec, 643 &res->acceptor_time_rec); 644 645 if ((res->status != GSS_S_COMPLETE) && 646 (res->status != GSS_S_DUPLICATE_ELEMENT) && 647 (gssd_debug)) 648 fprintf(stderr, gettext("gss_add_cred failed status %d \n"), 649 res->status); 650 /* 651 * convert the output args from the parameter given in the call to the 652 * variable in the XDR result 653 */ 654 if (actual_mechs != GSS_C_NULL_OID_SET) { 655 res->actual_mechs.GSS_OID_SET_len = 656 (uint_t)actual_mechs->count; 657 res->actual_mechs.GSS_OID_SET_val = (GSS_OID *) 658 malloc(sizeof (GSS_OID) * actual_mechs->count); 659 if (!res->actual_mechs.GSS_OID_SET_val) { 660 free(desired_mech_type->elements); 661 free(desired_mech_type); 662 return (GSS_S_FAILURE); 663 } 664 for (i = 0; i < actual_mechs->count; i++) { 665 res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_len = 666 (uint_t)actual_mechs->elements[i].length; 667 res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val = 668 (char *)malloc(actual_mechs->elements[i]. 669 length); 670 if (!res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val) { 671 free(desired_mech_type->elements); 672 free(desired_mech_type); 673 free(res->actual_mechs.GSS_OID_SET_val); 674 for (j = 0; j < (i - 1); j++) { 675 free 676 (res->actual_mechs. 677 GSS_OID_SET_val[j].GSS_OID_val); 678 } 679 return (GSS_S_FAILURE); 680 } 681 memcpy(res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val, 682 actual_mechs->elements[i].elements, 683 actual_mechs->elements[i].length); 684 } 685 } else 686 res->actual_mechs.GSS_OID_SET_len = 0; 687 688 /* 689 * now release the space allocated for 690 * desired_name and desired_mech_type 691 */ 692 693 gss_release_name(&minor_status, &desired_name); 694 free(desired_mech_type->elements); 695 gss_release_oid_set(&minor_status, &actual_mechs); 696 /* 697 * if (actual_mechs != GSS_C_NULL_OID_SET) { 698 * for (i = 0; i < actual_mechs->count; i++) 699 * free(actual_mechs->elements[i].elements); 700 * free(actual_mechs->elements); 701 * free(actual_mechs); 702 * } 703 */ 704 705 706 /* return to caller */ 707 708 return (TRUE); 709 } 710 711 bool_t 712 gss_release_cred_1_svc(argp, res, rqstp) 713 gss_release_cred_arg *argp; 714 gss_release_cred_res *res; 715 struct svc_req *rqstp; 716 { 717 718 uid_t uid; 719 gss_cred_id_t cred_handle; 720 721 memset(res, 0, sizeof (*res)); 722 723 if (gssd_debug) 724 fprintf(stderr, gettext("gss_release_cred\n")); 725 726 if (checkfrom(rqstp, &uid) == 0) 727 return (FALSE); 728 729 /* set the uid sent as the RPC argument */ 730 731 uid = argp->uid; 732 set_gssd_uid(uid); 733 734 /* 735 * if the cred_handle verifier is not correct, 736 * set status to GSS_S_DEFECTIVE_CREDENTIAL and return 737 */ 738 739 if (argp->gssd_cred_verifier != gssd_time_verf) { 740 res->status = (OM_uint32)GSS_S_DEFECTIVE_CREDENTIAL; 741 return (TRUE); 742 } 743 744 /* 745 * if the cred_handle length is 0 746 * set cred_handle argument to GSS_S_NO_CREDENTIAL 747 */ 748 749 if (argp->cred_handle.GSS_CRED_ID_T_len == 0) 750 cred_handle = GSS_C_NO_CREDENTIAL; 751 else 752 cred_handle = 753 (gss_cred_id_t)argp->cred_handle.GSS_CRED_ID_T_val; 754 755 /* call the gssapi routine */ 756 757 res->status = (OM_uint32)gss_release_cred(&res->minor_status, 758 &cred_handle); 759 760 /* return to caller */ 761 762 return (TRUE); 763 } 764 765 bool_t 766 gss_init_sec_context_1_svc(argp, res, rqstp) 767 gss_init_sec_context_arg *argp; 768 gss_init_sec_context_res *res; 769 struct svc_req *rqstp; 770 { 771 772 OM_uint32 minor_status; 773 gss_ctx_id_t context_handle; 774 bool_t context_verf_ok; 775 gss_cred_id_t claimant_cred_handle; 776 gss_buffer_desc external_name; 777 gss_OID_desc name_type_desc; 778 gss_OID name_type = &name_type_desc; 779 gss_name_t internal_name; 780 781 gss_OID_desc mech_type_desc; 782 gss_OID mech_type = &mech_type_desc; 783 struct gss_channel_bindings_struct 784 input_chan_bindings; 785 gss_channel_bindings_t input_chan_bindings_ptr; 786 gss_buffer_desc input_token; 787 gss_buffer_desc output_token; 788 gss_buffer_t input_token_ptr; 789 gss_OID actual_mech_type; 790 struct gssd_ctx_slot *slot = NULL; 791 792 uid_t uid; 793 794 memset(res, 0, sizeof (*res)); 795 796 if (gssd_debug) 797 fprintf(stderr, gettext("gss_init_sec_context\n")); 798 799 /* 800 * if the request isn't from root, null out the result pointer 801 * entries, so the next time through xdr_free won't try to 802 * free unmalloc'd memory and then return NULL 803 */ 804 805 if (checkfrom(rqstp, &uid) == 0) { 806 res->context_handle.GSS_CTX_ID_T_val = NULL; 807 res->actual_mech_type.GSS_OID_val = NULL; 808 res->output_token.GSS_BUFFER_T_val = NULL; 809 return (FALSE); 810 } 811 812 /* set the uid sent as the RPC argument */ 813 814 uid = argp->uid; 815 set_gssd_uid(uid); 816 817 /* 818 * copy the supplied context handle into the local context handle, so it 819 * can be supplied to the gss_init_sec_context call 820 */ 821 822 gssd_convert_context_handle(&argp->context_handle, &context_handle, 823 argp->gssd_context_verifier, &context_verf_ok, &slot); 824 825 claimant_cred_handle = 826 (argp->claimant_cred_handle.GSS_CRED_ID_T_len == 0 ? 827 GSS_C_NO_CREDENTIAL : 828 /*LINTED*/ 829 *((gss_cred_id_t *)argp->claimant_cred_handle. 830 GSS_CRED_ID_T_val)); 831 832 if (claimant_cred_handle != GSS_C_NO_CREDENTIAL) { 833 /* verify the verifier_cred_handle */ 834 if (argp->gssd_cred_verifier != gssd_time_verf) { 835 res->context_handle.GSS_CTX_ID_T_val = NULL; 836 res->output_token.GSS_BUFFER_T_val = NULL; 837 res->actual_mech_type.GSS_OID_val = NULL; 838 res->context_handle.GSS_CTX_ID_T_len = 0; 839 res->output_token.GSS_BUFFER_T_len = 0; 840 res->actual_mech_type.GSS_OID_len = 0; 841 res->status = (OM_uint32)GSS_S_DEFECTIVE_CREDENTIAL; 842 res->minor_status = 0; 843 return (TRUE); 844 } 845 } 846 847 if (context_handle != GSS_C_NO_CONTEXT) { 848 /* verify the verifier_context_handle */ 849 850 if (!context_verf_ok) { 851 res->context_handle.GSS_CTX_ID_T_val = NULL; 852 res->output_token.GSS_BUFFER_T_val = NULL; 853 res->actual_mech_type.GSS_OID_val = NULL; 854 res->context_handle.GSS_CTX_ID_T_len = 0; 855 res->output_token.GSS_BUFFER_T_len = 0; 856 res->actual_mech_type.GSS_OID_len = 0; 857 res->status = (OM_uint32)GSS_S_NO_CONTEXT; 858 res->minor_status = 0; 859 return (TRUE); 860 } 861 } 862 863 /* convert the target name from external to internal format */ 864 865 external_name.length = argp->target_name.GSS_BUFFER_T_len; 866 external_name.value = (void *)argp->target_name.GSS_BUFFER_T_val; 867 868 if (argp->name_type.GSS_OID_len == 0) { 869 name_type = GSS_C_NULL_OID; 870 } else { 871 name_type->length = argp->name_type.GSS_OID_len; 872 name_type->elements = (void *)malloc(name_type->length); 873 if (!name_type->elements) 874 return (GSS_S_FAILURE); 875 memcpy(name_type->elements, argp->name_type.GSS_OID_val, 876 name_type->length); 877 } 878 879 if (argp->mech_type.GSS_OID_len == 0) 880 mech_type = GSS_C_NULL_OID; 881 else { 882 mech_type->length = (OM_uint32)argp->mech_type.GSS_OID_len; 883 mech_type->elements = (void *)argp->mech_type.GSS_OID_val; 884 } 885 886 if (gss_import_name(&minor_status, &external_name, name_type, 887 &internal_name) != GSS_S_COMPLETE) { 888 889 if (name_type != GSS_C_NULL_OID) 890 free(name_type->elements); 891 res->status = (OM_uint32)GSS_S_FAILURE; 892 res->minor_status = minor_status; 893 894 return (TRUE); 895 } 896 /* 897 * copy the XDR structured arguments into their corresponding local GSSAPI 898 * variables. 899 */ 900 901 if (argp->input_chan_bindings.present == YES) { 902 input_chan_bindings_ptr = &input_chan_bindings; 903 input_chan_bindings.initiator_addrtype = 904 (OM_uint32)argp->input_chan_bindings. 905 initiator_addrtype; 906 input_chan_bindings.initiator_address.length = 907 (uint_t)argp->input_chan_bindings.initiator_address. 908 GSS_BUFFER_T_len; 909 input_chan_bindings.initiator_address.value = 910 (void *)argp->input_chan_bindings.initiator_address. 911 GSS_BUFFER_T_val; 912 input_chan_bindings.acceptor_addrtype = 913 (OM_uint32)argp->input_chan_bindings.acceptor_addrtype; 914 input_chan_bindings.acceptor_address.length = 915 (uint_t)argp->input_chan_bindings.acceptor_address. 916 GSS_BUFFER_T_len; 917 input_chan_bindings.acceptor_address.value = 918 (void *)argp->input_chan_bindings.acceptor_address. 919 GSS_BUFFER_T_val; 920 input_chan_bindings.application_data.length = 921 (uint_t)argp->input_chan_bindings.application_data. 922 GSS_BUFFER_T_len; 923 input_chan_bindings.application_data.value = 924 (void *)argp->input_chan_bindings.application_data. 925 GSS_BUFFER_T_val; 926 } else { 927 input_chan_bindings_ptr = GSS_C_NO_CHANNEL_BINDINGS; 928 input_chan_bindings.initiator_addrtype = 0; 929 input_chan_bindings.initiator_address.length = 0; 930 input_chan_bindings.initiator_address.value = 0; 931 input_chan_bindings.acceptor_addrtype = 0; 932 input_chan_bindings.acceptor_address.length = 0; 933 input_chan_bindings.acceptor_address.value = 0; 934 input_chan_bindings.application_data.length = 0; 935 input_chan_bindings.application_data.value = 0; 936 } 937 938 if (argp->input_token.GSS_BUFFER_T_len == 0) { 939 input_token_ptr = GSS_C_NO_BUFFER; 940 } else { 941 input_token_ptr = &input_token; 942 input_token.length = (size_t) 943 argp->input_token.GSS_BUFFER_T_len; 944 input_token.value = (void *)argp->input_token.GSS_BUFFER_T_val; 945 } 946 947 /* call the gssapi routine */ 948 949 res->status = (OM_uint32)gss_init_sec_context(&res->minor_status, 950 (gss_cred_id_t)argp->claimant_cred_handle. 951 GSS_CRED_ID_T_val, 952 &context_handle, 953 internal_name, 954 mech_type, 955 argp->req_flags, 956 argp->time_req, 957 input_chan_bindings_ptr, 958 input_token_ptr, 959 &actual_mech_type, 960 &output_token, 961 &res->ret_flags, 962 &res->time_rec); 963 964 /* 965 * convert the output args from the parameter given in the call to the 966 * variable in the XDR result 967 */ 968 969 if (res->status == (OM_uint32)GSS_S_COMPLETE || 970 res->status == (OM_uint32)GSS_S_CONTINUE_NEEDED) { 971 972 if (slot == NULL || slot->ctx != context_handle) { 973 /* 974 * Note that gssd_alloc_slot() will delete ctx's as long 975 * as we don't call gssd_rel_slot(). 976 */ 977 slot = gssd_alloc_slot(context_handle); 978 } 979 980 res->gssd_context_verifier = slot->verf; 981 982 res->context_handle.GSS_CTX_ID_T_len = sizeof (gss_ctx_id_t); 983 res->context_handle.GSS_CTX_ID_T_val = 984 (void *)malloc(sizeof (gss_ctx_id_t)); 985 if (!res->context_handle.GSS_CTX_ID_T_val) { 986 free(name_type->elements); 987 return (GSS_S_FAILURE); 988 } 989 990 memcpy(res->context_handle.GSS_CTX_ID_T_val, &slot->rpcctx, 991 sizeof (gss_ctx_id_t)); 992 993 res->output_token.GSS_BUFFER_T_len = 994 (uint_t)output_token.length; 995 res->output_token.GSS_BUFFER_T_val = 996 (char *)output_token.value; 997 998 /* 999 * the actual mech type parameter 1000 * is ready only upon GSS_S_COMPLETE 1001 */ 1002 if (res->status == GSS_S_COMPLETE) { 1003 res->actual_mech_type.GSS_OID_len = 1004 (uint_t)actual_mech_type->length; 1005 res->actual_mech_type.GSS_OID_val = 1006 (void *)malloc(actual_mech_type->length); 1007 if (!res->actual_mech_type.GSS_OID_val) { 1008 free(name_type->elements); 1009 free(res->context_handle.GSS_CTX_ID_T_val); 1010 return (GSS_S_FAILURE); 1011 } 1012 memcpy(res->actual_mech_type.GSS_OID_val, 1013 (char *)actual_mech_type->elements, 1014 actual_mech_type->length); 1015 } else 1016 res->actual_mech_type.GSS_OID_len = 0; 1017 } else { 1018 if (context_handle != GSS_C_NO_CONTEXT) { 1019 (void) gss_delete_sec_context(&minor_status, 1020 &context_handle, NULL); 1021 } 1022 res->context_handle.GSS_CTX_ID_T_len = 0; 1023 res->actual_mech_type.GSS_OID_len = 0; 1024 res->output_token.GSS_BUFFER_T_len = 0; 1025 } 1026 1027 /* 1028 * now release the space allocated by the underlying gssapi mechanism 1029 * library for internal_name and for the name_type. 1030 */ 1031 1032 gss_release_name(&minor_status, &internal_name); 1033 if (name_type != GSS_C_NULL_OID) 1034 free(name_type->elements); 1035 1036 1037 /* return to caller */ 1038 return (TRUE); 1039 } 1040 1041 bool_t 1042 gss_accept_sec_context_1_svc(argp, res, rqstp) 1043 gss_accept_sec_context_arg *argp; 1044 gss_accept_sec_context_res *res; 1045 struct svc_req *rqstp; 1046 { 1047 uid_t uid; 1048 OM_uint32 minor_status; 1049 gss_ctx_id_t context_handle = NULL; 1050 gss_cred_id_t verifier_cred_handle; 1051 gss_buffer_desc external_name; 1052 gss_name_t internal_name = NULL; 1053 1054 gss_buffer_desc input_token_buffer; 1055 gss_buffer_t input_token_buffer_ptr; 1056 struct gss_channel_bindings_struct 1057 input_chan_bindings; 1058 gss_channel_bindings_t input_chan_bindings_ptr; 1059 gss_OID mech_type; 1060 gss_buffer_desc output_token; 1061 gss_cred_id_t delegated_cred_handle; 1062 bool_t context_verf_ok; 1063 struct gssd_ctx_slot *slot = NULL; 1064 1065 memset(res, 0, sizeof (*res)); 1066 1067 if (gssd_debug) 1068 fprintf(stderr, gettext("gss_accept_sec_context\n")); 1069 1070 /* 1071 * if the request isn't from root, null out the result pointer 1072 * entries, so the next time through xdr_free won't try to 1073 * free unmalloc'd memory and then return NULL 1074 */ 1075 1076 if (checkfrom(rqstp, &uid) == 0) { 1077 res->context_handle.GSS_CTX_ID_T_val = NULL; 1078 res->src_name.GSS_BUFFER_T_val = NULL; 1079 res->mech_type.GSS_OID_val = NULL; 1080 res->output_token.GSS_BUFFER_T_val = NULL; 1081 res->delegated_cred_handle.GSS_CRED_ID_T_val = NULL; 1082 return (FALSE); 1083 } 1084 1085 /* set the uid sent as the RPC argument */ 1086 1087 uid = argp->uid; 1088 set_gssd_uid(uid); 1089 1090 /* 1091 * copy the supplied context handle into the local context handle, so 1092 * it can be supplied to the gss_accept_sec_context call 1093 */ 1094 1095 gssd_convert_context_handle(&argp->context_handle, &context_handle, 1096 argp->gssd_context_verifier, &context_verf_ok, &slot); 1097 1098 if (context_handle != GSS_C_NO_CONTEXT) 1099 /* verify the context_handle */ 1100 if (!context_verf_ok) { 1101 res->context_handle.GSS_CTX_ID_T_val = NULL; 1102 res->src_name.GSS_BUFFER_T_val = NULL; 1103 res->mech_type.GSS_OID_val = NULL; 1104 res->output_token.GSS_BUFFER_T_val = NULL; 1105 res->delegated_cred_handle.GSS_CRED_ID_T_val = NULL; 1106 res->src_name.GSS_BUFFER_T_len = 0; 1107 res->context_handle.GSS_CTX_ID_T_len = 0; 1108 res->delegated_cred_handle.GSS_CRED_ID_T_len = 0; 1109 res->output_token.GSS_BUFFER_T_len = 0; 1110 res->mech_type.GSS_OID_len = 0; 1111 res->status = (OM_uint32)GSS_S_NO_CONTEXT; 1112 res->minor_status = 0; 1113 return (TRUE); 1114 } 1115 1116 /* 1117 * copy the XDR structured arguments into their corresponding local 1118 * GSSAPI variable equivalents. 1119 */ 1120 1121 1122 verifier_cred_handle = 1123 (argp->verifier_cred_handle.GSS_CRED_ID_T_len == 0 ? 1124 GSS_C_NO_CREDENTIAL : 1125 /*LINTED*/ 1126 *((gss_cred_id_t *)argp->verifier_cred_handle. 1127 GSS_CRED_ID_T_val)); 1128 1129 if (verifier_cred_handle != GSS_C_NO_CREDENTIAL) 1130 /* verify the verifier_cred_handle */ 1131 if (argp->gssd_cred_verifier != gssd_time_verf) { 1132 res->context_handle.GSS_CTX_ID_T_val = NULL; 1133 res->src_name.GSS_BUFFER_T_val = NULL; 1134 res->mech_type.GSS_OID_val = NULL; 1135 res->output_token.GSS_BUFFER_T_val = NULL; 1136 res->delegated_cred_handle.GSS_CRED_ID_T_val = NULL; 1137 res->src_name.GSS_BUFFER_T_len = 0; 1138 res->context_handle.GSS_CTX_ID_T_len = 0; 1139 res->delegated_cred_handle.GSS_CRED_ID_T_len = 0; 1140 res->output_token.GSS_BUFFER_T_len = 0; 1141 res->mech_type.GSS_OID_len = 0; 1142 res->status = (OM_uint32)GSS_S_DEFECTIVE_CREDENTIAL; 1143 res->minor_status = 0; 1144 return (TRUE); 1145 } 1146 1147 if (argp->input_token_buffer.GSS_BUFFER_T_len == 0) { 1148 input_token_buffer_ptr = GSS_C_NO_BUFFER; 1149 } else { 1150 input_token_buffer_ptr = &input_token_buffer; 1151 input_token_buffer.length = (size_t)argp->input_token_buffer. 1152 GSS_BUFFER_T_len; 1153 input_token_buffer.value = (void *)argp->input_token_buffer. 1154 GSS_BUFFER_T_val; 1155 } 1156 1157 if (argp->input_chan_bindings.present == YES) { 1158 input_chan_bindings_ptr = &input_chan_bindings; 1159 input_chan_bindings.initiator_addrtype = 1160 (OM_uint32)argp->input_chan_bindings. 1161 initiator_addrtype; 1162 input_chan_bindings.initiator_address.length = 1163 (uint_t)argp->input_chan_bindings.initiator_address. 1164 GSS_BUFFER_T_len; 1165 input_chan_bindings.initiator_address.value = 1166 (void *)argp->input_chan_bindings.initiator_address. 1167 GSS_BUFFER_T_val; 1168 input_chan_bindings.acceptor_addrtype = 1169 (OM_uint32)argp->input_chan_bindings. 1170 acceptor_addrtype; 1171 input_chan_bindings.acceptor_address.length = 1172 (uint_t)argp->input_chan_bindings.acceptor_address. 1173 GSS_BUFFER_T_len; 1174 input_chan_bindings.acceptor_address.value = 1175 (void *)argp->input_chan_bindings.acceptor_address. 1176 GSS_BUFFER_T_val; 1177 input_chan_bindings.application_data.length = 1178 (uint_t)argp->input_chan_bindings.application_data. 1179 GSS_BUFFER_T_len; 1180 input_chan_bindings.application_data.value = 1181 (void *)argp->input_chan_bindings.application_data. 1182 GSS_BUFFER_T_val; 1183 } else { 1184 input_chan_bindings_ptr = GSS_C_NO_CHANNEL_BINDINGS; 1185 input_chan_bindings.initiator_addrtype = 0; 1186 input_chan_bindings.initiator_address.length = 0; 1187 input_chan_bindings.initiator_address.value = 0; 1188 input_chan_bindings.acceptor_addrtype = 0; 1189 input_chan_bindings.acceptor_address.length = 0; 1190 input_chan_bindings.acceptor_address.value = 0; 1191 input_chan_bindings.application_data.length = 0; 1192 input_chan_bindings.application_data.value = 0; 1193 } 1194 1195 1196 /* call the gssapi routine */ 1197 1198 res->status = (OM_uint32)gss_accept_sec_context(&res->minor_status, 1199 &context_handle, 1200 verifier_cred_handle, 1201 input_token_buffer_ptr, 1202 input_chan_bindings_ptr, 1203 &internal_name, 1204 &mech_type, 1205 &output_token, 1206 &res->ret_flags, 1207 &res->time_rec, 1208 &delegated_cred_handle); 1209 1210 /* convert the src name from internal to external format */ 1211 1212 if (res->status == (OM_uint32)GSS_S_COMPLETE || 1213 res->status == (OM_uint32)GSS_S_CONTINUE_NEEDED) { 1214 1215 /* 1216 * upon GSS_S_CONTINUE_NEEDED only the following 1217 * parameters are ready: minor, ctxt, and output token 1218 */ 1219 res->context_handle.GSS_CTX_ID_T_len = sizeof (gss_ctx_id_t); 1220 res->context_handle.GSS_CTX_ID_T_val = 1221 (void *)malloc(sizeof (gss_ctx_id_t)); 1222 if (!res->context_handle.GSS_CTX_ID_T_val) { 1223 res->status = (OM_uint32)GSS_S_FAILURE; 1224 res->minor_status = 0; 1225 return (TRUE); 1226 } 1227 1228 if (slot == NULL || slot->ctx != context_handle) { 1229 /* 1230 * Note that gssd_alloc_slot() will delete ctx's as long 1231 * as we don't call gssd_rel_slot(). 1232 */ 1233 slot = gssd_alloc_slot(context_handle); 1234 } 1235 1236 memcpy(res->context_handle.GSS_CTX_ID_T_val, &slot->rpcctx, 1237 sizeof (gss_ctx_id_t)); 1238 res->gssd_context_verifier = slot->verf; 1239 1240 res->output_token.GSS_BUFFER_T_len = 1241 (uint_t)output_token.length; 1242 res->output_token.GSS_BUFFER_T_val = 1243 (char *)output_token.value; 1244 1245 if (res->status == GSS_S_COMPLETE) { 1246 if (gss_export_name(&minor_status, internal_name, 1247 &external_name) 1248 != GSS_S_COMPLETE) { 1249 1250 res->status = (OM_uint32)GSS_S_FAILURE; 1251 res->minor_status = minor_status; 1252 gss_release_name(&minor_status, &internal_name); 1253 gss_delete_sec_context(&minor_status, 1254 &context_handle, NULL); 1255 free(res->context_handle.GSS_CTX_ID_T_val); 1256 res->context_handle.GSS_CTX_ID_T_val = NULL; 1257 res->context_handle.GSS_CTX_ID_T_len = 0; 1258 gss_release_buffer(&minor_status, 1259 &output_token); 1260 res->output_token.GSS_BUFFER_T_len = 0; 1261 res->output_token.GSS_BUFFER_T_val = NULL; 1262 return (TRUE); 1263 } 1264 res->src_name.GSS_BUFFER_T_len = 1265 (uint_t)external_name.length; 1266 res->src_name.GSS_BUFFER_T_val = 1267 (void *)external_name.value; 1268 1269 res->delegated_cred_handle.GSS_CRED_ID_T_len = 1270 sizeof (gss_cred_id_t); 1271 res->delegated_cred_handle.GSS_CRED_ID_T_val = 1272 (void *)malloc(sizeof (gss_cred_id_t)); 1273 if (!res->delegated_cred_handle.GSS_CRED_ID_T_val) { 1274 free(res->context_handle.GSS_CTX_ID_T_val); 1275 gss_release_name(&minor_status, &internal_name); 1276 gss_delete_sec_context(&minor_status, 1277 &context_handle, NULL); 1278 gss_release_buffer(&minor_status, 1279 &external_name); 1280 res->status = (OM_uint32)GSS_S_FAILURE; 1281 res->minor_status = 0; 1282 return (TRUE); 1283 } 1284 memcpy(res->delegated_cred_handle.GSS_CRED_ID_T_val, 1285 &delegated_cred_handle, 1286 sizeof (gss_cred_id_t)); 1287 1288 res->mech_type.GSS_OID_len = (uint_t)mech_type->length; 1289 res->mech_type.GSS_OID_val = 1290 (void *)malloc(mech_type->length); 1291 if (!res->mech_type.GSS_OID_val) { 1292 free(res->context_handle.GSS_CTX_ID_T_val); 1293 free(res->delegated_cred_handle.GSS_CRED_ID_T_val); 1294 gss_release_name(&minor_status, &internal_name); 1295 gss_delete_sec_context(&minor_status, 1296 &context_handle, NULL); 1297 gss_release_buffer(&minor_status, &external_name); 1298 res->status = (OM_uint32)GSS_S_FAILURE; 1299 res->minor_status = 0; 1300 return (TRUE); 1301 } 1302 memcpy(res->mech_type.GSS_OID_val, mech_type->elements, 1303 mech_type->length); 1304 1305 /* release the space allocated for internal_name */ 1306 gss_release_name(&minor_status, &internal_name); 1307 1308 } else { /* GSS_S_CONTINUE_NEEDED */ 1309 res->src_name.GSS_BUFFER_T_len = 0; 1310 res->delegated_cred_handle.GSS_CRED_ID_T_len = 0; 1311 res->mech_type.GSS_OID_len = 0; 1312 } 1313 } else { 1314 if (context_handle != GSS_C_NO_CONTEXT) { 1315 (void) gss_delete_sec_context(&minor_status, 1316 &context_handle, NULL); 1317 } 1318 res->src_name.GSS_BUFFER_T_len = 0; 1319 res->context_handle.GSS_CTX_ID_T_len = 0; 1320 res->delegated_cred_handle.GSS_CRED_ID_T_len = 0; 1321 res->output_token.GSS_BUFFER_T_len = 0; 1322 res->mech_type.GSS_OID_len = 0; 1323 } 1324 1325 /* return to caller */ 1326 1327 return (TRUE); 1328 } 1329 1330 bool_t 1331 gss_process_context_token_1_svc(argp, res, rqstp) 1332 gss_process_context_token_arg *argp; 1333 gss_process_context_token_res *res; 1334 struct svc_req *rqstp; 1335 { 1336 1337 uid_t uid; 1338 gss_buffer_desc token_buffer; 1339 gss_ctx_id_t context_handle; 1340 bool_t context_verf_ok; 1341 1342 memset(res, 0, sizeof (*res)); 1343 1344 if (gssd_debug) 1345 fprintf(stderr, gettext("gss_process_context_token\n")); 1346 1347 if (checkfrom(rqstp, &uid) == 0) 1348 return (FALSE); 1349 1350 gssd_convert_context_handle(&argp->context_handle, &context_handle, 1351 argp->gssd_context_verifier, &context_verf_ok, NULL); 1352 1353 /* verify the context_handle */ 1354 1355 if (!context_verf_ok) { 1356 res->status = (OM_uint32) GSS_S_NO_CONTEXT; 1357 res->minor_status = 0; 1358 return (TRUE); 1359 } 1360 1361 /* set the uid sent as the RPC argument */ 1362 1363 uid = argp->uid; 1364 set_gssd_uid(uid); 1365 1366 /* 1367 * copy the XDR structured arguments into their corresponding local 1368 * GSSAPI variable equivalents. 1369 */ 1370 1371 token_buffer.length = (size_t)argp->token_buffer.GSS_BUFFER_T_len; 1372 token_buffer.value = (void *)argp->token_buffer.GSS_BUFFER_T_val; 1373 1374 1375 /* call the gssapi routine */ 1376 1377 res->status = (OM_uint32)gss_process_context_token(&res->minor_status, 1378 context_handle, 1379 &token_buffer); 1380 1381 1382 /* return to caller */ 1383 1384 return (TRUE); 1385 } 1386 1387 bool_t 1388 gss_delete_sec_context_1_svc(argp, res, rqstp) 1389 gss_delete_sec_context_arg *argp; 1390 gss_delete_sec_context_res *res; 1391 struct svc_req *rqstp; 1392 { 1393 uid_t uid; 1394 gss_ctx_id_t context_handle; 1395 gss_buffer_desc output_token; 1396 bool_t context_verf_ok; 1397 struct gssd_ctx_slot *slot = NULL; 1398 1399 memset(res, 0, sizeof (*res)); 1400 1401 if (gssd_debug) 1402 fprintf(stderr, gettext("gss_delete_sec_context\n")); 1403 1404 1405 /* 1406 * copy the supplied context handle into the local context handle, so it 1407 * can be supplied to the gss_delete_sec_context call 1408 */ 1409 gssd_convert_context_handle(&argp->context_handle, &context_handle, 1410 argp->gssd_context_verifier, &context_verf_ok, &slot); 1411 1412 /* verify the context_handle */ 1413 if (!context_verf_ok) { 1414 res->context_handle.GSS_CTX_ID_T_val = NULL; 1415 res->context_handle.GSS_CTX_ID_T_len = 0; 1416 res->output_token.GSS_BUFFER_T_val = NULL; 1417 res->output_token.GSS_BUFFER_T_len = 0; 1418 res->status = (OM_uint32)GSS_S_NO_CONTEXT; 1419 res->minor_status = 0; 1420 return (TRUE); 1421 } 1422 1423 /* 1424 * if the request isn't from root, null out the result pointer 1425 * entries, so the next time through xdr_free won't try to 1426 * free unmalloc'd memory and then return NULL 1427 */ 1428 1429 if (checkfrom(rqstp, &uid) == 0) { 1430 res->context_handle.GSS_CTX_ID_T_val = NULL; 1431 res->output_token.GSS_BUFFER_T_val = NULL; 1432 return (FALSE); 1433 } 1434 1435 /* call the gssapi routine */ 1436 1437 res->status = (OM_uint32)gss_delete_sec_context(&res->minor_status, 1438 &context_handle, 1439 &output_token); 1440 1441 /* 1442 * convert the output args from the parameter given in the call to the 1443 * variable in the XDR result. If the delete succeeded, return a zero 1444 * context handle. 1445 */ 1446 1447 if (res->status == GSS_S_COMPLETE) { 1448 if (context_handle != GSS_C_NO_CONTEXT) 1449 return (GSS_S_FAILURE); 1450 res->context_handle.GSS_CTX_ID_T_len = 0; 1451 res->context_handle.GSS_CTX_ID_T_val = NULL; 1452 res->output_token.GSS_BUFFER_T_len = 1453 (uint_t)output_token.length; 1454 res->output_token.GSS_BUFFER_T_val = 1455 (char *)output_token.value; 1456 1457 if (slot != NULL) { 1458 /* 1459 * gss_delete_sec_context deletes the context if it 1460 * succeeds so clear slot->ctx to avoid a dangling 1461 * reference. 1462 */ 1463 slot->ctx = GSS_C_NO_CONTEXT; 1464 gssd_rel_slot(slot); 1465 } 1466 } else { 1467 res->context_handle.GSS_CTX_ID_T_len = sizeof (gss_ctx_id_t); 1468 res->context_handle.GSS_CTX_ID_T_val = 1469 (void *)malloc(sizeof (gss_ctx_id_t)); 1470 if (!res->context_handle.GSS_CTX_ID_T_val) { 1471 return (GSS_S_FAILURE); 1472 } 1473 1474 if (slot == NULL || slot->ctx != context_handle) { 1475 /* 1476 * Note that gssd_alloc_slot() will delete ctx's as long 1477 * as we don't call gssd_rel_slot(). 1478 */ 1479 slot = gssd_alloc_slot(context_handle); 1480 /* 1481 * Note that no verifier is returned in the .x 1482 * protocol. So if the context changes, we won't 1483 * be able to release it now. So it will have to 1484 * be LRUed out. 1485 */ 1486 } 1487 1488 memcpy(res->context_handle.GSS_CTX_ID_T_val, &slot->rpcctx, 1489 sizeof (gss_ctx_id_t)); 1490 1491 res->output_token.GSS_BUFFER_T_len = 0; 1492 res->output_token.GSS_BUFFER_T_val = NULL; 1493 } 1494 1495 /* return to caller */ 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