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 * GSSAPI library stub module for gssd. 28 */ 29 30 #include <mechglueP.h> 31 #include "gssd_prot.h" 32 #include <rpc/rpc.h> 33 34 #include <sys/systm.h> 35 #include <sys/types.h> 36 #include <sys/cmn_err.h> 37 #include <sys/kmem.h> 38 #include <gssapi/kgssapi_defs.h> 39 #include <sys/debug.h> 40 41 #ifdef GSSDEBUG 42 /* 43 * Kernel kgssd module debugging aid. The global variable "gss_log" 44 * is a bit mask which allows various types of debugging messages 45 * to be printed out. 46 * 47 * gss_log & 1 will cause actual failures to be printed. 48 * gss_log & 2 will cause informational messages to be 49 * printed on the client side of kgssd. 50 * gss_log & 4 will cause informational messages to be 51 * printed on the server side of kgssd. 52 * gss_log & 8 will cause informational messages to be 53 * printed on both client and server side of kgssd. 54 */ 55 56 uint_t gss_log = 1; 57 58 #endif /* GSSDEBUG */ 59 60 #ifdef DEBUG 61 extern void prom_printf(); 62 #endif 63 64 char *server = "localhost"; 65 66 static OM_uint32 kgss_sign_wrapped(void *, OM_uint32 *, gss_ctx_id_t, int, 67 gss_buffer_t, gss_buffer_t, OM_uint32); 68 69 static OM_uint32 kgss_verify_wrapped(void *, OM_uint32 *, gss_ctx_id_t, 70 gss_buffer_t, gss_buffer_t, int *qop_state, OM_uint32); 71 72 /* EXPORT DELETE START */ 73 static OM_uint32 kgss_seal_wrapped(void *, OM_uint32 *, gss_ctx_id_t, 74 int, int, gss_buffer_t, int *, gss_buffer_t, OM_uint32); 75 76 static OM_uint32 kgss_unseal_wrapped(void *, OM_uint32 *, gss_ctx_id_t, 77 gss_buffer_t, gss_buffer_t, int *conf_state, int *qop_state, 78 OM_uint32); 79 /* EXPORT DELETE END */ 80 81 static OM_uint32 kgss_delete_sec_context_wrapped(void *, OM_uint32 *, 82 gssd_ctx_id_t *, gss_buffer_t, OM_uint32); 83 84 static void __kgss_reset_mech(gss_mechanism *, gss_OID); 85 86 #define DEFAULT_MINOR_STAT ((OM_uint32) ~0) 87 88 OM_uint32 89 kgss_acquire_cred_wrapped(minor_status, 90 desired_name, 91 time_req, 92 desired_mechs, 93 cred_usage, 94 output_cred_handle, 95 actual_mechs, 96 time_rec, 97 uid, 98 gssd_cred_verifier) 99 OM_uint32 *minor_status; 100 const gss_name_t desired_name; 101 OM_uint32 time_req; 102 const gss_OID_set desired_mechs; 103 int cred_usage; 104 gssd_cred_id_t *output_cred_handle; 105 gss_OID_set *actual_mechs; 106 OM_uint32 *time_rec; 107 uid_t uid; 108 OM_uint32 *gssd_cred_verifier; 109 { 110 CLIENT *clnt; 111 112 OM_uint32 minor_status_temp; 113 gss_buffer_desc external_name; 114 gss_OID name_type; 115 enum clnt_stat client_stat; 116 int i; 117 118 gss_acquire_cred_arg arg; 119 gss_acquire_cred_res res; 120 121 /* get the client handle to GSSD */ 122 123 if ((clnt = getgssd_handle()) == NULL) { 124 GSSLOG(1, "kgss_acquire_cred: can't connect to server on %s\n", 125 server); 126 return (GSS_S_FAILURE); 127 } 128 129 /* convert the desired name from internal to external format */ 130 131 if (gss_display_name(&minor_status_temp, desired_name, &external_name, 132 &name_type) != GSS_S_COMPLETE) { 133 134 *minor_status = (OM_uint32) minor_status_temp; 135 killgssd_handle(clnt); 136 GSSLOG0(1, "kgss_acquire_cred: display name failed\n"); 137 return ((OM_uint32) GSS_S_FAILURE); 138 } 139 140 141 /* copy the procedure arguments into the rpc arg parameter */ 142 143 arg.uid = (OM_uint32) uid; 144 145 arg.desired_name.GSS_BUFFER_T_len = (uint_t)external_name.length; 146 arg.desired_name.GSS_BUFFER_T_val = (char *)external_name.value; 147 148 arg.name_type.GSS_OID_len = 149 name_type == GSS_C_NULL_OID ? 150 0 : (uint_t)name_type->length; 151 152 arg.name_type.GSS_OID_val = 153 name_type == GSS_C_NULL_OID ? 154 (char *)NULL : (char *)name_type->elements; 155 156 arg.time_req = time_req; 157 158 if (desired_mechs != GSS_C_NULL_OID_SET) { 159 arg.desired_mechs.GSS_OID_SET_len = 160 (uint_t)desired_mechs->count; 161 arg.desired_mechs.GSS_OID_SET_val = (GSS_OID *) 162 MALLOC(sizeof (GSS_OID) * desired_mechs->count); 163 164 for (i = 0; i < desired_mechs->count; i++) { 165 arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_len = 166 (uint_t)desired_mechs->elements[i].length; 167 arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val = 168 (char *)MALLOC(desired_mechs->elements[i].length); 169 (void) memcpy( 170 arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val, 171 desired_mechs->elements[i].elements, 172 desired_mechs->elements[i].length); 173 } 174 } else 175 arg.desired_mechs.GSS_OID_SET_len = 0; 176 177 arg.cred_usage = cred_usage; 178 179 /* call the remote procedure */ 180 181 bzero((caddr_t)&res, sizeof (res)); 182 client_stat = gss_acquire_cred_1(&arg, &res, clnt); 183 184 (void) gss_release_buffer(&minor_status_temp, &external_name); 185 if (desired_mechs != GSS_C_NULL_OID_SET) { 186 for (i = 0; i < desired_mechs->count; i++) 187 FREE(arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val, 188 arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_len); 189 FREE(arg.desired_mechs.GSS_OID_SET_val, 190 arg.desired_mechs.GSS_OID_SET_len * sizeof (GSS_OID)); 191 } 192 193 if (client_stat != RPC_SUCCESS) { 194 195 /* 196 * if the RPC call times out, null out all return arguments, 197 * set minor_status to its maximum value, and return 198 * GSS_S_FAILURE 199 */ 200 201 if (minor_status != NULL) 202 *minor_status = DEFAULT_MINOR_STAT; 203 if (output_cred_handle != NULL) 204 *output_cred_handle = NULL; 205 if (actual_mechs != NULL) 206 *actual_mechs = NULL; 207 if (time_rec != NULL) 208 *time_rec = 0; 209 210 killgssd_handle(clnt); 211 GSSLOG0(1, "kgss_acquire_cred: RPC call times out\n"); 212 return (GSS_S_FAILURE); 213 } 214 215 /* copy the rpc results into the return arguments */ 216 217 if (minor_status != NULL) 218 *minor_status = res.minor_status; 219 220 if (output_cred_handle != NULL && 221 (res.status == GSS_S_COMPLETE)) { 222 *output_cred_handle = 223 *((gssd_cred_id_t *)res.output_cred_handle.GSS_CRED_ID_T_val); 224 *gssd_cred_verifier = res.gssd_cred_verifier; 225 } 226 227 if (res.status == GSS_S_COMPLETE && 228 res.actual_mechs.GSS_OID_SET_len != 0 && 229 actual_mechs != NULL) { 230 *actual_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc)); 231 (*actual_mechs)->count = 232 (int)res.actual_mechs.GSS_OID_SET_len; 233 (*actual_mechs)->elements = (gss_OID) 234 MALLOC(sizeof (gss_OID_desc) * (*actual_mechs)->count); 235 236 for (i = 0; i < (*actual_mechs)->count; i++) { 237 (*actual_mechs)->elements[i].length = (OM_uint32) 238 res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_len; 239 (*actual_mechs)->elements[i].elements = 240 (void *) MALLOC((*actual_mechs)->elements[i].length); 241 (void) memcpy((*actual_mechs)->elements[i].elements, 242 res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_val, 243 (*actual_mechs)->elements[i].length); 244 } 245 } else { 246 if (res.status == GSS_S_COMPLETE && 247 actual_mechs != NULL) 248 (*actual_mechs) = NULL; 249 } 250 251 if (time_rec != NULL) 252 *time_rec = res.time_rec; 253 254 /* 255 * free the memory allocated for the results and return with the status 256 * received in the rpc call 257 */ 258 259 clnt_freeres(clnt, xdr_gss_acquire_cred_res, (caddr_t)&res); 260 killgssd_handle(clnt); 261 return (res.status); 262 263 } 264 265 OM_uint32 266 kgss_acquire_cred(minor_status, 267 desired_name, 268 time_req, 269 desired_mechs, 270 cred_usage, 271 output_cred_handle, 272 actual_mechs, 273 time_rec, 274 uid) 275 OM_uint32 *minor_status; 276 const gss_name_t desired_name; 277 OM_uint32 time_req; 278 const gss_OID_set desired_mechs; 279 int cred_usage; 280 gss_cred_id_t *output_cred_handle; 281 gss_OID_set *actual_mechs; 282 OM_uint32 *time_rec; 283 uid_t uid; 284 { 285 286 OM_uint32 err; 287 struct kgss_cred *kcred; 288 289 kcred = KGSS_CRED_ALLOC(); 290 *output_cred_handle = (gss_cred_id_t)kcred; 291 err = kgss_acquire_cred_wrapped(minor_status, desired_name, time_req, 292 desired_mechs, cred_usage, &kcred->gssd_cred, actual_mechs, 293 time_rec, uid, &kcred->gssd_cred_verifier); 294 if (GSS_ERROR(err)) { 295 KGSS_CRED_FREE(kcred); 296 *output_cred_handle = GSS_C_NO_CREDENTIAL; 297 } 298 return (err); 299 } 300 301 OM_uint32 302 kgss_add_cred_wrapped(minor_status, 303 input_cred_handle, 304 gssd_cred_verifier, 305 desired_name, 306 desired_mech_type, 307 cred_usage, 308 initiator_time_req, 309 acceptor_time_req, 310 actual_mechs, 311 initiator_time_rec, 312 acceptor_time_rec, 313 uid) 314 OM_uint32 *minor_status; 315 gssd_cred_id_t input_cred_handle; 316 OM_uint32 gssd_cred_verifier; 317 gss_name_t desired_name; 318 gss_OID desired_mech_type; 319 int cred_usage; 320 int initiator_time_req; 321 int acceptor_time_req; 322 gss_OID_set *actual_mechs; 323 OM_uint32 *initiator_time_rec; 324 OM_uint32 *acceptor_time_rec; 325 uid_t uid; 326 { 327 CLIENT *clnt; 328 329 OM_uint32 minor_status_temp; 330 gss_buffer_desc external_name; 331 gss_OID name_type; 332 int i; 333 334 gss_add_cred_arg arg; 335 gss_add_cred_res res; 336 337 338 /* 339 * NULL the params here once 340 * If there are errors then we won't 341 * have to do it for every error 342 * case 343 */ 344 345 if (minor_status != NULL) 346 *minor_status = DEFAULT_MINOR_STAT; 347 if (actual_mechs != NULL) 348 *actual_mechs = NULL; 349 if (initiator_time_rec != NULL) 350 *initiator_time_rec = 0; 351 if (acceptor_time_rec != NULL) 352 *acceptor_time_rec = 0; 353 /* get the client handle to GSSD */ 354 355 if ((clnt = getgssd_handle()) == NULL) { 356 GSSLOG(1, "kgss_add_cred: can't connect to server on %s\n", 357 server); 358 return (GSS_S_FAILURE); 359 } 360 361 362 /* convert the desired name from internal to external format */ 363 364 if (gss_display_name(&minor_status_temp, desired_name, &external_name, 365 &name_type) != GSS_S_COMPLETE) { 366 367 *minor_status = (OM_uint32) minor_status_temp; 368 killgssd_handle(clnt); 369 GSSLOG0(1, "kgss_acquire_cred: display name failed\n"); 370 return ((OM_uint32) GSS_S_FAILURE); 371 } 372 373 374 /* copy the procedure arguments into the rpc arg parameter */ 375 376 arg.uid = (OM_uint32)uid; 377 arg.input_cred_handle.GSS_CRED_ID_T_len = 378 input_cred_handle == 379 (gssd_cred_id_t)GSS_C_NO_CREDENTIAL ? 380 0 : (uint_t)sizeof (gssd_cred_id_t); 381 arg.input_cred_handle.GSS_CRED_ID_T_val = (char *)&input_cred_handle; 382 arg.gssd_cred_verifier = gssd_cred_verifier; 383 arg.desired_name.GSS_BUFFER_T_len = (uint_t)external_name.length; 384 arg.desired_name.GSS_BUFFER_T_val = (char *)external_name.value; 385 arg.name_type.GSS_OID_len = 386 name_type == GSS_C_NULL_OID ? 387 0 : (uint_t)name_type->length; 388 arg.name_type.GSS_OID_val = 389 name_type == GSS_C_NULL_OID ? 390 (char *)NULL : (char *)name_type->elements; 391 392 arg.desired_mech_type.GSS_OID_len = 393 (uint_t)(desired_mech_type != GSS_C_NULL_OID ? 394 desired_mech_type->length : 0); 395 arg.desired_mech_type.GSS_OID_val = 396 (char *)(desired_mech_type != GSS_C_NULL_OID ? 397 desired_mech_type->elements : 0); 398 arg.cred_usage = cred_usage; 399 arg.initiator_time_req = initiator_time_req; 400 arg.acceptor_time_req = acceptor_time_req; 401 402 /* call the remote procedure */ 403 404 bzero((caddr_t)&res, sizeof (res)); 405 if (gss_add_cred_1(&arg, &res, clnt) != RPC_SUCCESS) { 406 407 /* 408 * if the RPC call times out, null out all return arguments, 409 * set minor_status to its maximum value, and return 410 * GSS_S_FAILURE 411 */ 412 413 killgssd_handle(clnt); 414 (void) gss_release_buffer(&minor_status_temp, &external_name); 415 GSSLOG0(1, "kgss_add_cred: RPC call times out\n"); 416 return (GSS_S_FAILURE); 417 } 418 419 /* free the allocated memory for the flattened name */ 420 421 (void) gss_release_buffer(&minor_status_temp, &external_name); 422 423 /* copy the rpc results into the return arguments */ 424 425 if (minor_status != NULL) 426 *minor_status = res.minor_status; 427 428 if (res.status == GSS_S_COMPLETE && 429 res.actual_mechs.GSS_OID_SET_len != 0 && 430 actual_mechs != NULL) { 431 *actual_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc)); 432 (*actual_mechs)->count = 433 (int)res.actual_mechs.GSS_OID_SET_len; 434 (*actual_mechs)->elements = (gss_OID) 435 MALLOC(sizeof (gss_OID_desc) * (*actual_mechs)->count); 436 437 for (i = 0; i < (*actual_mechs)->count; i++) { 438 (*actual_mechs)->elements[i].length = (OM_uint32) 439 res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_len; 440 (*actual_mechs)->elements[i].elements = 441 (void *) MALLOC((*actual_mechs)->elements[i].length); 442 (void) memcpy((*actual_mechs)->elements[i].elements, 443 res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_val, 444 (*actual_mechs)->elements[i].length); 445 } 446 } else { 447 if (res.status == GSS_S_COMPLETE && actual_mechs != NULL) 448 (*actual_mechs) = NULL; 449 } 450 if (initiator_time_rec != NULL) 451 *initiator_time_rec = res.acceptor_time_rec; 452 if (acceptor_time_rec != NULL) 453 *acceptor_time_rec = res.acceptor_time_rec; 454 455 /* 456 * free the memory allocated for the results and return with the status 457 * received in the rpc call 458 */ 459 460 clnt_freeres(clnt, xdr_gss_add_cred_res, (caddr_t)&res); 461 killgssd_handle(clnt); 462 return (res.status); 463 464 } 465 466 OM_uint32 467 kgss_add_cred(minor_status, 468 input_cred_handle, 469 desired_name, 470 desired_mech_type, 471 cred_usage, 472 initiator_time_req, 473 acceptor_time_req, 474 actual_mechs, 475 initiator_time_rec, 476 acceptor_time_rec, 477 uid) 478 OM_uint32 *minor_status; 479 gss_cred_id_t input_cred_handle; 480 gss_name_t desired_name; 481 gss_OID desired_mech_type; 482 int cred_usage; 483 int initiator_time_req; 484 int acceptor_time_req; 485 gss_OID_set *actual_mechs; 486 OM_uint32 *initiator_time_rec; 487 OM_uint32 *acceptor_time_rec; 488 uid_t uid; 489 { 490 491 OM_uint32 err; 492 OM_uint32 gssd_cred_verifier; 493 gssd_cred_id_t gssd_input_cred_handle; 494 495 if (input_cred_handle != GSS_C_NO_CREDENTIAL) { 496 gssd_cred_verifier = KCRED_TO_CREDV(input_cred_handle); 497 gssd_input_cred_handle = KCRED_TO_CRED(input_cred_handle); 498 } else 499 gssd_input_cred_handle = (gssd_cred_id_t)GSS_C_NO_CREDENTIAL; 500 501 err = kgss_add_cred_wrapped(minor_status, gssd_input_cred_handle, 502 gssd_cred_verifier, desired_name, desired_mech_type, 503 cred_usage, initiator_time_req, acceptor_time_req, 504 actual_mechs, initiator_time_rec, 505 acceptor_time_rec, uid); 506 return (err); 507 } 508 509 510 OM_uint32 511 kgss_release_cred_wrapped(minor_status, 512 cred_handle, 513 uid, 514 gssd_cred_verifier) 515 OM_uint32 *minor_status; 516 gssd_cred_id_t *cred_handle; 517 uid_t uid; 518 OM_uint32 gssd_cred_verifier; 519 { 520 CLIENT *clnt; 521 522 gss_release_cred_arg arg; 523 gss_release_cred_res res; 524 525 526 /* get the client handle to GSSD */ 527 528 if ((clnt = getgssd_handle()) == NULL) { 529 GSSLOG(1, "kgss_release_cred: can't connect to server on %s\n", 530 server); 531 return (GSS_S_FAILURE); 532 } 533 534 /* copy the procedure arguments into the rpc arg parameter */ 535 536 arg.uid = (OM_uint32)uid; 537 arg.gssd_cred_verifier = gssd_cred_verifier; 538 539 if (cred_handle != NULL) { 540 arg.cred_handle.GSS_CRED_ID_T_len = 541 (uint_t)sizeof (gssd_cred_id_t); 542 arg.cred_handle.GSS_CRED_ID_T_val = (char *)cred_handle; 543 } else 544 arg.cred_handle.GSS_CRED_ID_T_len = 0; 545 546 /* call the remote procedure */ 547 548 bzero((caddr_t)&res, sizeof (res)); 549 if (gss_release_cred_1(&arg, &res, clnt) != RPC_SUCCESS) { 550 551 /* 552 * if the RPC call times out, null out all return arguments, set 553 * minor_status to its maximum value, and return GSS_S_FAILURE 554 */ 555 556 if (minor_status != NULL) 557 *minor_status = DEFAULT_MINOR_STAT; 558 if (cred_handle != NULL) 559 *cred_handle = NULL; 560 561 killgssd_handle(clnt); 562 GSSLOG0(1, "kgss_release_cred: RPC call times out\n"); 563 return (GSS_S_FAILURE); 564 } 565 566 /* if the release succeeded, null out the cred_handle */ 567 568 if (res.status == GSS_S_COMPLETE && cred_handle != NULL) 569 *cred_handle = NULL; 570 571 /* copy the rpc results into the return arguments */ 572 573 if (minor_status != NULL) 574 *minor_status = res.minor_status; 575 576 /* return with status returned in rpc call */ 577 578 killgssd_handle(clnt); 579 580 return (res.status); 581 582 } 583 584 OM_uint32 585 kgss_release_cred(minor_status, 586 cred_handle, 587 uid) 588 OM_uint32 *minor_status; 589 gss_cred_id_t *cred_handle; 590 uid_t uid; 591 592 { 593 594 OM_uint32 err; 595 struct kgss_cred *kcred; 596 597 if (*cred_handle == GSS_C_NO_CREDENTIAL) 598 return (GSS_S_COMPLETE); 599 else 600 kcred = KCRED_TO_KGSS_CRED(*cred_handle); 601 602 err = kgss_release_cred_wrapped(minor_status, &kcred->gssd_cred, 603 uid, kcred->gssd_cred_verifier); 604 KGSS_CRED_FREE(kcred); 605 *cred_handle = GSS_C_NO_CREDENTIAL; 606 return (err); 607 } 608 609 static OM_uint32 610 kgss_init_sec_context_wrapped( 611 OM_uint32 *minor_status, 612 const gssd_cred_id_t claimant_cred_handle, 613 OM_uint32 gssd_cred_verifier, 614 gssd_ctx_id_t *context_handle, 615 OM_uint32 *gssd_context_verifier, 616 const gss_name_t target_name, 617 const gss_OID mech_type, 618 int req_flags, 619 OM_uint32 time_req, 620 const gss_channel_bindings_t input_chan_bindings, 621 const gss_buffer_t input_token, 622 gss_OID *actual_mech_type, 623 gss_buffer_t output_token, 624 int *ret_flags, 625 OM_uint32 *time_rec, 626 uid_t uid) 627 { 628 CLIENT *clnt; 629 630 OM_uint32 minor_status_temp; 631 gss_buffer_desc external_name; 632 gss_OID name_type; 633 634 gss_init_sec_context_arg arg; 635 gss_init_sec_context_res res; 636 637 /* get the client handle to GSSD */ 638 639 if ((clnt = getgssd_handle()) == NULL) { 640 GSSLOG(1, 641 "kgss_init_sec_context: can't connect to server on %s\n", 642 server); 643 return (GSS_S_FAILURE); 644 } 645 646 /* convert the target name from internal to external format */ 647 648 if (gss_display_name(&minor_status_temp, target_name, 649 &external_name, &name_type) != GSS_S_COMPLETE) { 650 651 *minor_status = (OM_uint32) minor_status_temp; 652 killgssd_handle(clnt); 653 GSSLOG0(1, "kgss_init_sec_context: can't display name\n"); 654 return ((OM_uint32) GSS_S_FAILURE); 655 } 656 657 658 /* copy the procedure arguments into the rpc arg parameter */ 659 660 arg.uid = (OM_uint32)uid; 661 662 arg.context_handle.GSS_CTX_ID_T_len = 663 *context_handle == (gssd_ctx_id_t)GSS_C_NO_CONTEXT ? 664 0 : (uint_t)sizeof (gssd_ctx_id_t); 665 arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle; 666 667 arg.gssd_context_verifier = *gssd_context_verifier; 668 669 arg.claimant_cred_handle.GSS_CRED_ID_T_len = 670 claimant_cred_handle == (gssd_cred_id_t)GSS_C_NO_CREDENTIAL ? 671 0 : (uint_t)sizeof (gssd_cred_id_t); 672 arg.claimant_cred_handle.GSS_CRED_ID_T_val = 673 (char *)&claimant_cred_handle; 674 arg.gssd_cred_verifier = gssd_cred_verifier; 675 676 arg.target_name.GSS_BUFFER_T_len = (uint_t)external_name.length; 677 arg.target_name.GSS_BUFFER_T_val = (char *)external_name.value; 678 679 arg.name_type.GSS_OID_len = 680 name_type == GSS_C_NULL_OID ? 681 0 : (uint_t)name_type->length; 682 683 arg.name_type.GSS_OID_val = 684 name_type == GSS_C_NULL_OID ? 685 (char *)NULL : (char *)name_type->elements; 686 687 arg.mech_type.GSS_OID_len = (uint_t)(mech_type != GSS_C_NULL_OID ? 688 mech_type->length : 0); 689 arg.mech_type.GSS_OID_val = (char *)(mech_type != GSS_C_NULL_OID ? 690 mech_type->elements : 0); 691 692 arg.req_flags = req_flags; 693 694 arg.time_req = time_req; 695 696 if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) { 697 arg.input_chan_bindings.present = YES; 698 arg.input_chan_bindings.initiator_addrtype = 699 input_chan_bindings->initiator_addrtype; 700 arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = 701 (uint_t)input_chan_bindings->initiator_address.length; 702 arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = 703 (void *)input_chan_bindings->initiator_address.value; 704 arg.input_chan_bindings.acceptor_addrtype = 705 input_chan_bindings->acceptor_addrtype; 706 arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = 707 (uint_t)input_chan_bindings->acceptor_address.length; 708 arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = 709 (void *)input_chan_bindings->acceptor_address.value; 710 arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = 711 (uint_t)input_chan_bindings->application_data.length; 712 arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = 713 (void *)input_chan_bindings->application_data.value; 714 } else { 715 arg.input_chan_bindings.present = NO; 716 arg.input_chan_bindings.initiator_addrtype = 0; 717 arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = 0; 718 arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = 0; 719 arg.input_chan_bindings.acceptor_addrtype = 0; 720 arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = 0; 721 arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = 0; 722 arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = 0; 723 arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = 0; 724 } 725 726 arg.input_token.GSS_BUFFER_T_len = 727 (uint_t)(input_token != GSS_C_NO_BUFFER ? 728 input_token->length : 0); 729 arg.input_token.GSS_BUFFER_T_val = 730 (char *)(input_token != GSS_C_NO_BUFFER ? 731 input_token->value : 0); 732 733 /* call the remote procedure */ 734 735 bzero((caddr_t)&res, sizeof (res)); 736 if (gss_init_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) { 737 738 /* 739 * if the RPC call times out, null out all return arguments, set 740 * minor_status to its maximum value, and return GSS_S_FAILURE 741 */ 742 743 if (minor_status != NULL) 744 *minor_status = DEFAULT_MINOR_STAT; 745 if (actual_mech_type != NULL) 746 *actual_mech_type = NULL; 747 if (output_token != NULL) 748 output_token->length = 0; 749 if (ret_flags != NULL) 750 *ret_flags = 0; 751 if (time_rec != NULL) 752 *time_rec = 0; 753 754 killgssd_handle(clnt); 755 (void) gss_release_buffer(&minor_status_temp, &external_name); 756 GSSLOG0(1, "kgss_init_sec_context: RPC call times out\n"); 757 return (GSS_S_FAILURE); 758 } 759 760 /* free the allocated memory for the flattened name */ 761 762 (void) gss_release_buffer(&minor_status_temp, &external_name); 763 764 if (minor_status != NULL) 765 *minor_status = res.minor_status; 766 767 if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) { 768 output_token->length = 769 (size_t)res.output_token.GSS_BUFFER_T_len; 770 output_token->value = 771 (void *)MALLOC(output_token->length); 772 (void) memcpy(output_token->value, 773 res.output_token.GSS_BUFFER_T_val, 774 output_token->length); 775 } 776 777 /* if the call was successful, copy out the results */ 778 if (res.status == (OM_uint32) GSS_S_COMPLETE || 779 res.status == (OM_uint32) GSS_S_CONTINUE_NEEDED) { 780 /* 781 * if the return code is GSS_S_CONTINUE_NEEDED 782 * ignore all return parameters except for 783 * status codes, output token and context handle. 784 */ 785 *context_handle = 786 *((gssd_ctx_id_t *) 787 res.context_handle.GSS_CTX_ID_T_val); 788 *gssd_context_verifier = res.gssd_context_verifier; 789 790 if (res.status == GSS_S_COMPLETE) { 791 if (actual_mech_type != NULL) { 792 *actual_mech_type = 793 (gss_OID) MALLOC(sizeof (gss_OID_desc)); 794 (*actual_mech_type)->length = 795 (OM_UINT32) 796 res.actual_mech_type.GSS_OID_len; 797 (*actual_mech_type)->elements = 798 (void *) 799 MALLOC((*actual_mech_type)->length); 800 (void) memcpy((*actual_mech_type)->elements, 801 (void *) 802 res.actual_mech_type.GSS_OID_val, 803 (*actual_mech_type)->length); 804 } 805 806 807 if (ret_flags != NULL) 808 *ret_flags = res.ret_flags; 809 810 if (time_rec != NULL) 811 *time_rec = res.time_rec; 812 } 813 } 814 815 /* 816 * free the memory allocated for the results and return with the status 817 * received in the rpc call 818 */ 819 820 clnt_freeres(clnt, xdr_gss_init_sec_context_res, (caddr_t)&res); 821 killgssd_handle(clnt); 822 return (res.status); 823 824 } 825 826 static struct gss_config default_gc = { 827 { 0, NULL}, 828 NULL, 829 NULL, 830 0, 831 /* EXPORT DELETE START */ /* CRYPT DELETE START */ 832 kgss_unseal_wrapped, 833 /* EXPORT DELETE END */ /* CRYPT DELETE END */ 834 NULL, /* kgss_delete_sec_context_wrapped */ 835 /* EXPORT DELETE START */ /* CRYPT DELETE START */ 836 kgss_seal_wrapped, 837 /* EXPORT DELETE END */ /* CRYPT DELETE END */ 838 NULL, /* kgss_import_sec_context */ 839 /* EXPORT DELETE START */ 840 /* CRYPT DELETE START */ 841 #if 0 842 /* CRYPT DELETE END */ 843 kgss_seal_wrapped, 844 kgss_unseal_wrapped, 845 /* CRYPT DELETE START */ 846 #endif 847 /* CRYPT DELETE END */ 848 /* EXPORT DELETE END */ 849 kgss_sign_wrapped, 850 kgss_verify_wrapped 851 }; 852 853 void 854 kgss_free_oid(gss_OID oid) 855 { 856 FREE(oid->elements, oid->length); 857 FREE(oid, sizeof (gss_OID_desc)); 858 } 859 860 OM_uint32 861 kgss_init_sec_context( 862 OM_uint32 *minor_status, 863 const gss_cred_id_t claimant_cred_handle, 864 gss_ctx_id_t *context_handle, 865 const gss_name_t target_name, 866 const gss_OID mech_type, 867 int req_flags, 868 OM_uint32 time_req, 869 const gss_channel_bindings_t input_chan_bindings, 870 const gss_buffer_t input_token, 871 gss_OID *actual_mech_type, 872 gss_buffer_t output_token, 873 int *ret_flags, 874 OM_uint32 *time_rec, 875 uid_t uid) 876 { 877 OM_uint32 err; 878 struct kgss_ctx *kctx; 879 gss_OID amt; 880 gssd_cred_id_t gssd_cl_cred_handle; 881 OM_uint32 gssd_cred_verifier; 882 883 /* 884 * If this is an initial call, we'll need to create the 885 * wrapper struct that contains kernel state information, and 886 * a reference to the handle from gssd. 887 */ 888 if (*context_handle == GSS_C_NO_CONTEXT) { 889 kctx = KGSS_ALLOC(); 890 /* 891 * The default gss-mechanism struct as pointers to 892 * the sign/seal/verify/unseal routines that make 893 * upcalls to gssd. 894 */ 895 kctx->mech = &default_gc; 896 kctx->gssd_ctx = (gssd_ctx_id_t)GSS_C_NO_CONTEXT; 897 *context_handle = (gss_ctx_id_t)kctx; 898 } else 899 kctx = (struct kgss_ctx *)*context_handle; 900 901 if (claimant_cred_handle != GSS_C_NO_CREDENTIAL) { 902 gssd_cred_verifier = KCRED_TO_CREDV(claimant_cred_handle); 903 gssd_cl_cred_handle = KCRED_TO_CRED(claimant_cred_handle); 904 } else 905 gssd_cl_cred_handle = (gssd_cred_id_t)GSS_C_NO_CREDENTIAL; 906 907 /* 908 * We need to know the resulting mechanism oid, so allocate 909 * it if the caller won't. 910 */ 911 if (actual_mech_type == NULL) 912 actual_mech_type = &amt; 913 914 err = kgss_init_sec_context_wrapped(minor_status, gssd_cl_cred_handle, 915 gssd_cred_verifier, &kctx->gssd_ctx, &kctx->gssd_ctx_verifier, 916 target_name, mech_type, req_flags, time_req, 917 input_chan_bindings, input_token, actual_mech_type, 918 output_token, ret_flags, time_rec, uid); 919 920 if (GSS_ERROR(err)) { 921 KGSS_FREE(kctx); 922 *context_handle = GSS_C_NO_CONTEXT; 923 } else if (err == GSS_S_COMPLETE) { 924 /* 925 * Now check if there is a kernel module for this 926 * mechanism OID. If so, set the gss_mechanism structure 927 * in the wrapper context to point to the kernel mech. 928 */ 929 __kgss_reset_mech(&kctx->mech, *actual_mech_type); 930 931 /* 932 * If the mech oid was allocated for us, free it. 933 */ 934 if (&amt == actual_mech_type) { 935 kgss_free_oid(amt); 936 } 937 } 938 return (err); 939 } 940 941 static OM_uint32 942 kgss_accept_sec_context_wrapped( 943 OM_uint32 *minor_status, 944 gssd_ctx_id_t *context_handle, 945 OM_uint32 *gssd_context_verifier, 946 const gssd_cred_id_t verifier_cred_handle, 947 OM_uint32 gssd_cred_verifier, 948 const gss_buffer_t input_token, 949 const gss_channel_bindings_t input_chan_bindings, 950 gss_buffer_t src_name, 951 gss_OID *mech_type, 952 gss_buffer_t output_token, 953 int *ret_flags, 954 OM_uint32 *time_rec, 955 gss_cred_id_t *delegated_cred_handle, 956 uid_t uid) 957 { 958 CLIENT *clnt; 959 960 gss_accept_sec_context_arg arg; 961 gss_accept_sec_context_res res; 962 struct kgss_cred *kcred; 963 964 /* get the client handle to GSSD */ 965 966 if ((clnt = getgssd_handle()) == NULL) { 967 GSSLOG(1, 968 "kgss_accept_sec_context: can't connect to server on %s\n", 969 server); 970 return (GSS_S_FAILURE); 971 } 972 973 /* copy the procedure arguments into the rpc arg parameter */ 974 975 arg.uid = (OM_uint32)uid; 976 977 arg.context_handle.GSS_CTX_ID_T_len = 978 *context_handle == (gssd_ctx_id_t)GSS_C_NO_CONTEXT ? 979 0 : (uint_t)sizeof (gssd_ctx_id_t); 980 arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle; 981 arg.gssd_context_verifier = *gssd_context_verifier; 982 983 arg.verifier_cred_handle.GSS_CRED_ID_T_len = 984 verifier_cred_handle == 985 (gssd_cred_id_t)GSS_C_NO_CREDENTIAL ? 986 0 : (uint_t)sizeof (gssd_cred_id_t); 987 arg.verifier_cred_handle.GSS_CRED_ID_T_val = 988 (char *)&verifier_cred_handle; 989 arg.gssd_cred_verifier = gssd_cred_verifier; 990 991 arg.input_token_buffer.GSS_BUFFER_T_len = 992 (uint_t)(input_token != GSS_C_NO_BUFFER ? 993 input_token->length : 0); 994 arg.input_token_buffer.GSS_BUFFER_T_val = 995 (char *)(input_token != GSS_C_NO_BUFFER ? 996 input_token->value : 0); 997 998 if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) { 999 arg.input_chan_bindings.present = YES; 1000 arg.input_chan_bindings.initiator_addrtype = 1001 input_chan_bindings->initiator_addrtype; 1002 arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = 1003 (uint_t)input_chan_bindings->initiator_address.length; 1004 arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = 1005 (void *)input_chan_bindings->initiator_address.value; 1006 arg.input_chan_bindings.acceptor_addrtype = 1007 input_chan_bindings->acceptor_addrtype; 1008 arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = 1009 (uint_t)input_chan_bindings->acceptor_address.length; 1010 arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = 1011 (void *)input_chan_bindings->acceptor_address.value; 1012 arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = 1013 (uint_t)input_chan_bindings->application_data.length; 1014 arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = 1015 (void *)input_chan_bindings->application_data.value; 1016 } else { 1017 1018 arg.input_chan_bindings.present = NO; 1019 arg.input_chan_bindings.initiator_addrtype = 0; 1020 arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = 0; 1021 arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = 0; 1022 arg.input_chan_bindings.acceptor_addrtype = 0; 1023 arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = 0; 1024 arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = 0; 1025 arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = 0; 1026 arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = 0; 1027 } 1028 1029 /* set the return parameters in case of errors.... */ 1030 if (minor_status != NULL) 1031 *minor_status = DEFAULT_MINOR_STAT; 1032 if (src_name != NULL) { 1033 src_name->length = 0; 1034 src_name->value = NULL; 1035 } 1036 if (mech_type != NULL) 1037 *mech_type = NULL; 1038 if (output_token != NULL) 1039 output_token->length = 0; 1040 if (ret_flags != NULL) 1041 *ret_flags = 0; 1042 if (time_rec != NULL) 1043 *time_rec = 0; 1044 if (delegated_cred_handle != NULL) 1045 *delegated_cred_handle = NULL; 1046 1047 /* call the remote procedure */ 1048 1049 bzero((caddr_t)&res, sizeof (res)); 1050 if (gss_accept_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) { 1051 killgssd_handle(clnt); 1052 GSSLOG0(1, "kgss_accept_sec_context: RPC call times out\n"); 1053 return (GSS_S_FAILURE); 1054 } 1055 1056 if (minor_status != NULL) 1057 *minor_status = res.minor_status; 1058 1059 if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) { 1060 output_token->length = 1061 res.output_token.GSS_BUFFER_T_len; 1062 output_token->value = 1063 (void *) MALLOC(output_token->length); 1064 (void) memcpy(output_token->value, 1065 res.output_token.GSS_BUFFER_T_val, 1066 output_token->length); 1067 } 1068 1069 /* if the call was successful, copy out the results */ 1070 1071 if (res.status == (OM_uint32) GSS_S_COMPLETE || 1072 res.status == (OM_uint32) GSS_S_CONTINUE_NEEDED) { 1073 1074 /* 1075 * the only parameters that are ready when we 1076 * get GSS_S_CONTINUE_NEEDED are: minor, ctxt_handle, 1077 * and the output token to send to the peer. 1078 */ 1079 1080 *context_handle = *((gssd_ctx_id_t *) 1081 res.context_handle.GSS_CTX_ID_T_val); 1082 *gssd_context_verifier = res.gssd_context_verifier; 1083 1084 /* these other parameters are only ready upon GSS_S_COMPLETE */ 1085 if (res.status == (OM_uint32) GSS_S_COMPLETE) { 1086 1087 if (src_name != NULL) { 1088 src_name->length = res.src_name.GSS_BUFFER_T_len; 1089 src_name->value = res.src_name.GSS_BUFFER_T_val; 1090 res.src_name.GSS_BUFFER_T_val = NULL; 1091 res.src_name.GSS_BUFFER_T_len = 0; 1092 } 1093 1094 /* 1095 * move mech type returned to mech_type 1096 * for gss_import_name_for_mech() 1097 */ 1098 if (mech_type != NULL) { 1099 *mech_type = (gss_OID) 1100 MALLOC(sizeof (gss_OID_desc)); 1101 (*mech_type)->length = 1102 (OM_UINT32) res.mech_type.GSS_OID_len; 1103 (*mech_type)->elements = 1104 (void *) MALLOC((*mech_type)->length); 1105 (void) memcpy((*mech_type)->elements, 1106 res.mech_type.GSS_OID_val, 1107 (*mech_type)->length); 1108 } 1109 1110 if (ret_flags != NULL) 1111 *ret_flags = res.ret_flags; 1112 1113 if (time_rec != NULL) 1114 *time_rec = res.time_rec; 1115 1116 if ((delegated_cred_handle != NULL) && 1117 (res.delegated_cred_handle.GSS_CRED_ID_T_len 1118 != 0)) { 1119 kcred = KGSS_CRED_ALLOC(); 1120 kcred->gssd_cred = 1121 *((gssd_cred_id_t *) 1122 res.delegated_cred_handle.GSS_CRED_ID_T_val); 1123 kcred->gssd_cred_verifier = 1124 res.gssd_context_verifier; 1125 *delegated_cred_handle = (gss_cred_id_t)kcred; 1126 } 1127 1128 } 1129 } 1130 1131 1132 /* 1133 * free the memory allocated for the results and return with the status 1134 * received in the rpc call 1135 */ 1136 1137 clnt_freeres(clnt, xdr_gss_accept_sec_context_res, (caddr_t)&res); 1138 killgssd_handle(clnt); 1139 return (res.status); 1140 1141 } 1142 1143 OM_uint32 1144 kgss_accept_sec_context( 1145 OM_uint32 *minor_status, 1146 gss_ctx_id_t *context_handle, 1147 const gss_cred_id_t verifier_cred_handle, 1148 const gss_buffer_t input_token, 1149 const gss_channel_bindings_t input_chan_bindings, 1150 gss_buffer_t src_name, 1151 gss_OID *mech_type, 1152 gss_buffer_t output_token, 1153 int *ret_flags, 1154 OM_uint32 *time_rec, 1155 gss_cred_id_t *delegated_cred_handle, 1156 uid_t uid) 1157 { 1158 OM_uint32 err; 1159 struct kgss_ctx *kctx; 1160 gss_OID mt; 1161 OM_uint32 gssd_cred_verifier; 1162 gssd_cred_id_t gssd_ver_cred_handle; 1163 1164 1165 /* 1166 * See kgss_init_sec_context() to get an idea of what is going 1167 * on here. 1168 */ 1169 if (mech_type == NULL) 1170 mech_type = &mt; 1171 1172 if (*context_handle == GSS_C_NO_CONTEXT) { 1173 kctx = KGSS_ALLOC(); 1174 kctx->mech = &default_gc; 1175 kctx->gssd_ctx = (gssd_ctx_id_t)GSS_C_NO_CONTEXT; 1176 *context_handle = (gss_ctx_id_t)kctx; 1177 } else 1178 kctx = (struct kgss_ctx *)*context_handle; 1179 1180 if (verifier_cred_handle != GSS_C_NO_CREDENTIAL) { 1181 gssd_cred_verifier = KCRED_TO_CREDV(verifier_cred_handle); 1182 gssd_ver_cred_handle = KCRED_TO_CRED(verifier_cred_handle); 1183 } else 1184 gssd_ver_cred_handle = (gssd_cred_id_t)GSS_C_NO_CREDENTIAL; 1185 1186 err = kgss_accept_sec_context_wrapped(minor_status, 1187 &kctx->gssd_ctx, &kctx->gssd_ctx_verifier, 1188 gssd_ver_cred_handle, gssd_cred_verifier, 1189 input_token, input_chan_bindings, src_name, 1190 mech_type, output_token, ret_flags, 1191 time_rec, delegated_cred_handle, uid); 1192 1193 if (GSS_ERROR(err)) { 1194 KGSS_FREE(kctx); 1195 *context_handle = GSS_C_NO_CONTEXT; 1196 1197 } else if (err == GSS_S_COMPLETE) { 1198 __kgss_reset_mech(&kctx->mech, *mech_type); 1199 1200 /* 1201 * If the mech oid was allocated for us, free it. 1202 */ 1203 if (&mt == mech_type) { 1204 kgss_free_oid(mt); 1205 } 1206 } 1207 1208 return (err); 1209 } 1210 1211 OM_uint32 1212 kgss_process_context_token(minor_status, 1213 context_handle, 1214 token_buffer, 1215 uid) 1216 OM_uint32 *minor_status; 1217 const gss_ctx_id_t context_handle; 1218 gss_buffer_t token_buffer; 1219 uid_t uid; 1220 { 1221 CLIENT *clnt; 1222 OM_uint32 gssd_context_verifier; 1223 gssd_ctx_id_t gssd_ctx_handle; 1224 gss_process_context_token_arg arg; 1225 gss_process_context_token_res res; 1226 1227 gssd_context_verifier = KGSS_CTX_TO_GSSD_CTXV(context_handle); 1228 gssd_ctx_handle = (gssd_ctx_id_t)KGSS_CTX_TO_GSSD_CTX(context_handle); 1229 1230 /* get the client handle to GSSD */ 1231 1232 if ((clnt = getgssd_handle()) == NULL) { 1233 GSSLOG(1, 1234 "kgss_process_context_token: can't connect to server on %s\n", 1235 server); 1236 return (GSS_S_FAILURE); 1237 } 1238 1239 /* copy the procedure arguments into the rpc arg parameter */ 1240 1241 arg.uid = (OM_uint32) uid; 1242 1243 arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t); 1244 arg.context_handle.GSS_CTX_ID_T_val = (char *)&gssd_ctx_handle; 1245 arg.gssd_context_verifier = gssd_context_verifier; 1246 arg.token_buffer.GSS_BUFFER_T_len = (uint_t)token_buffer->length; 1247 arg.token_buffer.GSS_BUFFER_T_val = (char *)token_buffer->value; 1248 1249 /* call the remote procedure */ 1250 1251 bzero(&res, sizeof (res)); 1252 1253 if (gss_process_context_token_1(&arg, &res, clnt) != RPC_SUCCESS) { 1254 1255 /* 1256 * if the RPC call times out, null out all return arguments, set 1257 * minor_status to its maximum value, and return GSS_S_FAILURE 1258 */ 1259 1260 if (minor_status != NULL) 1261 *minor_status = DEFAULT_MINOR_STAT; 1262 GSSLOG0(1, "kgss_process_context_token: RPC call times out\n"); 1263 killgssd_handle(clnt); 1264 return (GSS_S_FAILURE); 1265 } 1266 1267 /* copy the rpc results into the return arguments */ 1268 1269 if (minor_status != NULL) 1270 *minor_status = res.minor_status; 1271 1272 /* return with status returned in rpc call */ 1273 1274 killgssd_handle(clnt); 1275 return (res.status); 1276 1277 } 1278 1279 /*ARGSUSED*/ 1280 static OM_uint32 1281 kgss_delete_sec_context_wrapped(void *private, 1282 OM_uint32 *minor_status, 1283 gssd_ctx_id_t *context_handle, 1284 gss_buffer_t output_token, 1285 OM_uint32 gssd_context_verifier) 1286 1287 1288 { 1289 CLIENT *clnt; 1290 1291 gss_delete_sec_context_arg arg; 1292 gss_delete_sec_context_res res; 1293 1294 1295 /* get the client handle to GSSD */ 1296 1297 if ((clnt = getgssd_handle()) == NULL) { 1298 GSSLOG(1, 1299 "kgss_delete_sec_context: can't connect to server on %s\n", 1300 server); 1301 return (GSS_S_FAILURE); 1302 } 1303 1304 /* copy the procedure arguments into the rpc arg parameter */ 1305 1306 arg.context_handle.GSS_CTX_ID_T_len = 1307 *context_handle == (gssd_ctx_id_t)GSS_C_NO_CONTEXT ? 1308 0 : (uint_t)sizeof (gssd_ctx_id_t); 1309 arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle; 1310 1311 arg.gssd_context_verifier = gssd_context_verifier; 1312 1313 /* call the remote procedure */ 1314 1315 bzero((caddr_t)&res, sizeof (res)); 1316 if (gss_delete_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) { 1317 1318 /* 1319 * if the RPC call times out, null out all return arguments, set 1320 * minor_status to its maximum value, and return GSS_S_FAILURE 1321 */ 1322 1323 if (minor_status != NULL) 1324 *minor_status = DEFAULT_MINOR_STAT; 1325 if (context_handle != NULL) 1326 *context_handle = NULL; 1327 if (output_token != NULL) 1328 output_token->length = 0; 1329 1330 killgssd_handle(clnt); 1331 GSSLOG0(1, "kgssd_delete_sec_context: RPC call times out\n"); 1332 return (GSS_S_FAILURE); 1333 } 1334 1335 /* copy the rpc results into the return arguments */ 1336 1337 if (minor_status != NULL) 1338 *minor_status = res.minor_status; 1339 1340 if (res.context_handle.GSS_CTX_ID_T_len == 0) 1341 *context_handle = NULL; 1342 else 1343 *context_handle = 1344 *((gssd_ctx_id_t *)res.context_handle.GSS_CTX_ID_T_val); 1345 1346 if (output_token != NULL) { 1347 output_token->length = res.output_token.GSS_BUFFER_T_len; 1348 output_token->value = res.output_token.GSS_BUFFER_T_val; 1349 res.output_token.GSS_BUFFER_T_len = 0; 1350 res.output_token.GSS_BUFFER_T_val = NULL; 1351 } 1352 1353 /* 1354 * free the memory allocated for the results and return with the status 1355 * received in the rpc call 1356 */ 1357 1358 clnt_freeres(clnt, xdr_gss_delete_sec_context_res, (caddr_t)&res); 1359 killgssd_handle(clnt); 1360 return (res.status); 1361 1362 } 1363 1364 OM_uint32 1365 kgss_delete_sec_context( 1366 OM_uint32 *minor_status, 1367 gss_ctx_id_t *context_handle, 1368 gss_buffer_t output_token) 1369 { 1370 OM_uint32 err; 1371 struct kgss_ctx *kctx; 1372 1373 if (*context_handle == GSS_C_NO_CONTEXT) { 1374 GSSLOG0(8, "kgss_delete_sec_context: Null context handle \n"); 1375 return (GSS_S_COMPLETE); 1376 } else 1377 kctx = (struct kgss_ctx *)*context_handle; 1378 1379 if (kctx->ctx_imported == FALSE) { 1380 if (kctx->gssd_ctx == (gssd_ctx_id_t)GSS_C_NO_CONTEXT) { 1381 KGSS_FREE(kctx); 1382 *context_handle = GSS_C_NO_CONTEXT; 1383 return (GSS_S_COMPLETE); 1384 } 1385 err = kgss_delete_sec_context_wrapped( 1386 KCTX_TO_PRIVATE(*context_handle), 1387 minor_status, 1388 &kctx->gssd_ctx, 1389 output_token, 1390 kctx->gssd_ctx_verifier); 1391 } else { 1392 if (kctx->gssd_i_ctx == (gss_ctx_id_t)GSS_C_NO_CONTEXT) { 1393 KGSS_FREE(kctx); 1394 *context_handle = GSS_C_NO_CONTEXT; 1395 return (GSS_S_COMPLETE); 1396 } 1397 err = KGSS_DELETE_SEC_CONTEXT(minor_status, kctx, 1398 &kctx->gssd_i_ctx, output_token); 1399 } 1400 KGSS_FREE(kctx); 1401 *context_handle = GSS_C_NO_CONTEXT; 1402 return (err); 1403 1404 } 1405 1406 1407 OM_uint32 1408 kgss_export_sec_context_wrapped(minor_status, 1409 context_handle, 1410 output_token, 1411 gssd_context_verifier) 1412 OM_uint32 *minor_status; 1413 gssd_ctx_id_t *context_handle; 1414 gss_buffer_t output_token; 1415 OM_uint32 gssd_context_verifier; 1416 { 1417 CLIENT *clnt; 1418 gss_export_sec_context_arg arg; 1419 gss_export_sec_context_res res; 1420 1421 1422 /* get the client handle to GSSD */ 1423 1424 if ((clnt = getgssd_handle()) == NULL) { 1425 GSSLOG(1, "kgss_export_sec_context_wrapped :" 1426 " can't connect to server on %s\n", server); 1427 return (GSS_S_FAILURE); 1428 } 1429 1430 /* copy the procedure arguments into the rpc arg parameter */ 1431 1432 arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t); 1433 arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle; 1434 arg.gssd_context_verifier = gssd_context_verifier; 1435 1436 /* call the remote procedure */ 1437 1438 (void) memset(&res, 0, sizeof (res)); 1439 if (gss_export_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) { 1440 1441 /* 1442 * if the RPC call times out, null out all return arguments, 1443 * set minor_status to its maximum value, and return 1444 * GSS_S_FAILURE 1445 */ 1446 1447 if (minor_status != NULL) 1448 *minor_status = DEFAULT_MINOR_STAT; 1449 if (context_handle != NULL) 1450 *context_handle = NULL; 1451 if (output_token != NULL) 1452 output_token->length = 0; 1453 killgssd_handle(clnt); 1454 GSSLOG0(1, 1455 "kgss_export_sec_context_wrapped: RPC call times out\n"); 1456 return (GSS_S_FAILURE); 1457 } 1458 1459 /* copy the rpc results into the return arguments */ 1460 1461 if (minor_status != NULL) 1462 *minor_status = res.minor_status; 1463 1464 if (res.context_handle.GSS_CTX_ID_T_len == 0) 1465 *context_handle = NULL; 1466 else 1467 *context_handle = 1468 *((gssd_ctx_id_t *)res.context_handle.GSS_CTX_ID_T_val); 1469 1470 if (output_token != NULL) { 1471 output_token->length = res.output_token.GSS_BUFFER_T_len; 1472 output_token->value = 1473 (void *) MALLOC(output_token->length); 1474 (void) memcpy(output_token->value, 1475 res.output_token.GSS_BUFFER_T_val, 1476 output_token->length); 1477 } 1478 1479 /* 1480 * free the memory allocated for the results and return with the status 1481 * received in the rpc call 1482 */ 1483 1484 clnt_freeres(clnt, xdr_gss_export_sec_context_res, (caddr_t)&res); 1485 killgssd_handle(clnt); 1486 return (res.status); 1487 1488 } 1489 1490 OM_uint32 1491 kgss_export_sec_context(minor_status, 1492 context_handle, 1493 output_token) 1494 OM_uint32 *minor_status; 1495 gss_ctx_id_t context_handle; 1496 gss_buffer_t output_token; 1497 { 1498 struct kgss_ctx *kctx; 1499 1500 if (context_handle == GSS_C_NO_CONTEXT) 1501 return (GSS_S_FAILURE); 1502 else 1503 kctx = (struct kgss_ctx *)context_handle; 1504 1505 1506 1507 /* 1508 * If there is a kernel module then import_sec context must be 1509 * supported and we make an upcall to export_sec_context. 1510 * If there is no kernel module then we return an error 1511 */ 1512 1513 *minor_status = 0; 1514 1515 if (kctx->mech->gss_import_sec_context) { 1516 GSSLOG0(8, "kgss_export_sec_context: Kernel mod available \n"); 1517 return (kgss_export_sec_context_wrapped(minor_status, 1518 &kctx->gssd_ctx, 1519 output_token, 1520 kctx->gssd_ctx_verifier)); 1521 1522 } else { 1523 1524 /* 1525 * This is not the right error value; instead of 1526 * inventing new error we return GSS_S_NAME_NOT_MN 1527 * This error is not returned by the export routine 1528 */ 1529 1530 GSSLOG0(8, "kgss_export_sec_context: Kernel mod " 1531 "unavailable \n"); 1532 return (GSS_S_NAME_NOT_MN); 1533 } 1534 1535 } 1536 1537 OM_uint32 1538 kgss_import_sec_context(minor_status, 1539 interprocess_token, 1540 context_handle) 1541 1542 OM_uint32 * minor_status; 1543 const gss_buffer_t interprocess_token; 1544 gss_ctx_id_t context_handle; 1545 1546 { 1547 OM_uint32 status; 1548 struct kgss_ctx *kctx; 1549 1550 size_t length; 1551 char *p; 1552 gss_buffer_desc token; 1553 gss_ctx_id_t internal_ctx_id; 1554 kctx = (struct kgss_ctx *)context_handle; 1555 1556 if (kctx->gssd_ctx != (gssd_ctx_id_t)GSS_C_NO_CONTEXT) { 1557 return (GSS_S_FAILURE); 1558 } 1559 1560 if (!(KCTX_TO_MECH(context_handle)->gss_import_sec_context)) { 1561 1562 /* 1563 * This should never happen 1564 * If Kernel import sec context does not exist the export 1565 * sec context should have caught this and returned an error 1566 * and the caller should not have called this routine 1567 */ 1568 GSSLOG0(1, "import_sec_context called improperly\n"); 1569 return (GSS_S_FAILURE); 1570 } 1571 *minor_status = 0; 1572 1573 if (interprocess_token->length == 0 || interprocess_token->value == 0) 1574 return (GSS_S_DEFECTIVE_TOKEN); 1575 1576 status = GSS_S_FAILURE; 1577 1578 p = interprocess_token->value; 1579 length = *p++; 1580 length = (length << 8) + *p++; 1581 length = (length << 8) + *p++; 1582 length = (length << 8) + *p++; 1583 1584 p += length; 1585 1586 token.length = interprocess_token->length - 4 - length; 1587 token.value = p; 1588 1589 /* 1590 * select the approprate underlying mechanism routine and 1591 * call it. 1592 */ 1593 1594 status = KGSS_IMPORT_SEC_CONTEXT(minor_status, &token, kctx, 1595 &internal_ctx_id); 1596 1597 if (status == GSS_S_COMPLETE) { 1598 KCTX_TO_I_CTX(kctx) = internal_ctx_id; 1599 kctx->ctx_imported = TRUE; 1600 return (GSS_S_COMPLETE); 1601 } else 1602 return (status); 1603 } 1604 1605 /*ARGSUSED*/ 1606 OM_uint32 1607 kgss_context_time(minor_status, 1608 context_handle, 1609 time_rec, 1610 uid) 1611 OM_uint32 *minor_status; 1612 const gss_ctx_id_t context_handle; 1613 OM_uint32 *time_rec; 1614 uid_t uid; 1615 { 1616 return (GSS_S_FAILURE); 1617 } 1618 1619 /*ARGSUSED*/ 1620 static OM_uint32 1621 kgss_sign_wrapped(void *private, 1622 OM_uint32 *minor_status, 1623 const gss_ctx_id_t ctx_handle, 1624 int qop_req, 1625 const gss_buffer_t message_buffer, 1626 gss_buffer_t msg_token, 1627 OM_uint32 gssd_context_verifier) 1628 { 1629 CLIENT *clnt; 1630 gssd_ctx_id_t context_handle; 1631 1632 gss_sign_arg arg; 1633 gss_sign_res res; 1634 context_handle = (gssd_ctx_id_t)KCTX_TO_GSSD_CTX(ctx_handle); 1635 /* get the client handle to GSSD */ 1636 1637 if ((clnt = getgssd_handle()) == NULL) { 1638 GSSLOG(1, "kgss_sign: can't connect to server on %s\n", server); 1639 return (GSS_S_FAILURE); 1640 } 1641 1642 /* copy the procedure arguments into the rpc arg parameter */ 1643 1644 arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t); 1645 arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle; 1646 1647 arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t); 1648 arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle; 1649 arg.gssd_context_verifier = gssd_context_verifier; 1650 1651 arg.qop_req = qop_req; 1652 1653 arg.message_buffer.GSS_BUFFER_T_len = (uint_t)message_buffer->length; 1654 arg.message_buffer.GSS_BUFFER_T_val = (char *)message_buffer->value; 1655 1656 /* call the remote procedure */ 1657 1658 bzero((caddr_t)&res, sizeof (res)); 1659 if (gss_sign_1(&arg, &res, clnt) != RPC_SUCCESS) { 1660 1661 /* 1662 * if the RPC call times out, null out all return arguments, set 1663 * minor_status to its maximum value, and return GSS_S_FAILURE 1664 */ 1665 1666 if (minor_status != NULL) 1667 *minor_status = DEFAULT_MINOR_STAT; 1668 if (msg_token != NULL) 1669 msg_token->length = 0; 1670 1671 killgssd_handle(clnt); 1672 GSSLOG0(1, "kgss_sign: RPC call times out\n"); 1673 return (GSS_S_FAILURE); 1674 } 1675 1676 /* copy the rpc results into the return arguments */ 1677 1678 if (minor_status != NULL) 1679 *minor_status = res.minor_status; 1680 1681 if (msg_token != NULL) { 1682 msg_token->length = res.msg_token.GSS_BUFFER_T_len; 1683 msg_token->value = (void *) MALLOC(msg_token->length); 1684 (void) memcpy(msg_token->value, res.msg_token.GSS_BUFFER_T_val, 1685 msg_token->length); 1686 } 1687 1688 /* 1689 * free the memory allocated for the results and return with the status 1690 * received in the rpc call 1691 */ 1692 1693 clnt_freeres(clnt, xdr_gss_sign_res, (caddr_t)&res); 1694 killgssd_handle(clnt); 1695 return (res.status); 1696 1697 } 1698 1699 OM_uint32 1700 kgss_sign( 1701 OM_uint32 *minor_status, 1702 const gss_ctx_id_t context_handle, 1703 int qop_req, 1704 const gss_buffer_t message_buffer, 1705 gss_buffer_t msg_token) 1706 { 1707 if (context_handle == GSS_C_NO_CONTEXT) 1708 return (GSS_S_FAILURE); 1709 return (KGSS_SIGN(minor_status, context_handle, qop_req, 1710 message_buffer, msg_token)); 1711 } 1712 1713 /*ARGSUSED*/ 1714 static OM_uint32 1715 kgss_verify_wrapped(void *private, 1716 OM_uint32 *minor_status, 1717 const gss_ctx_id_t ctx_handle, 1718 const gss_buffer_t message_buffer, 1719 const gss_buffer_t token_buffer, 1720 int *qop_state, 1721 OM_uint32 gssd_context_verifier) 1722 { 1723 CLIENT *clnt; 1724 1725 gssd_ctx_id_t context_handle; 1726 gss_verify_arg arg; 1727 gss_verify_res res; 1728 1729 context_handle = (gssd_ctx_id_t)KCTX_TO_GSSD_CTX(ctx_handle); 1730 1731 /* get the client handle to GSSD */ 1732 1733 if ((clnt = getgssd_handle()) == NULL) { 1734 GSSLOG(1, "kgss_verify: can't connect to server on %s\n", 1735 server); 1736 return (GSS_S_FAILURE); 1737 } 1738 1739 /* copy the procedure arguments into the rpc arg parameter */ 1740 1741 arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gss_ctx_id_t); 1742 arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle; 1743 1744 arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t); 1745 arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle; 1746 arg.gssd_context_verifier = gssd_context_verifier; 1747 1748 arg.message_buffer.GSS_BUFFER_T_len = (uint_t)message_buffer->length; 1749 arg.message_buffer.GSS_BUFFER_T_val = (char *)message_buffer->value; 1750 1751 arg.token_buffer.GSS_BUFFER_T_len = (uint_t)token_buffer->length; 1752 arg.token_buffer.GSS_BUFFER_T_val = (char *)token_buffer->value; 1753 1754 /* call the remote procedure */ 1755 1756 bzero((caddr_t)&res, sizeof (res)); 1757 if (gss_verify_1(&arg, &res, clnt) != RPC_SUCCESS) { 1758 1759 /* 1760 * if the RPC call times out, null out all return arguments, set 1761 * minor_status to its maximum value, and return GSS_S_FAILURE 1762 */ 1763 1764 if (minor_status != NULL) 1765 *minor_status = DEFAULT_MINOR_STAT; 1766 if (qop_state != NULL) 1767 *qop_state = 0; 1768 1769 killgssd_handle(clnt); 1770 GSSLOG0(1, "kgss_verify: RPC call times out\n"); 1771 return (GSS_S_FAILURE); 1772 } 1773 1774 /* copy the rpc results into the return arguments */ 1775 1776 if (minor_status != NULL) 1777 *minor_status = res.minor_status; 1778 1779 if (qop_state != NULL) 1780 *qop_state = res.qop_state; 1781 1782 /* return with status returned in rpc call */ 1783 1784 killgssd_handle(clnt); 1785 return (res.status); 1786 1787 } 1788 1789 OM_uint32 1790 kgss_verify(OM_uint32 *minor_status, 1791 const gss_ctx_id_t context_handle, 1792 const gss_buffer_t message_buffer, 1793 const gss_buffer_t token_buffer, 1794 int *qop_state) 1795 { 1796 if (context_handle == GSS_C_NO_CONTEXT) 1797 return (GSS_S_FAILURE); 1798 return (KGSS_VERIFY(minor_status, context_handle, 1799 message_buffer, 1800 token_buffer, 1801 qop_state)); 1802 } 1803 1804 /* EXPORT DELETE START */ 1805 1806 /*ARGSUSED*/ 1807 static OM_uint32 1808 kgss_seal_wrapped(void *private, 1809 OM_uint32 *minor_status, 1810 const gss_ctx_id_t ctx_handle, 1811 int conf_req_flag, 1812 int qop_req, 1813 const gss_buffer_t input_message_buffer, 1814 int *conf_state, 1815 gss_buffer_t output_message_buffer, 1816 OM_uint32 gssd_context_verifier) 1817 { 1818 CLIENT *clnt; 1819 gssd_ctx_id_t context_handle; 1820 1821 gss_seal_arg arg; 1822 gss_seal_res res; 1823 1824 context_handle = (gssd_ctx_id_t)KCTX_TO_GSSD_CTX(ctx_handle); 1825 1826 /* get the client handle to GSSD */ 1827 1828 if ((clnt = getgssd_handle()) == NULL) { 1829 GSSLOG(1, "kgss_seal: can't connect to server on %s\n", server); 1830 return (GSS_S_FAILURE); 1831 } 1832 1833 /* copy the procedure arguments into the rpc arg parameter */ 1834 1835 arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gss_ctx_id_t); 1836 arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle; 1837 1838 arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (OM_uint32); 1839 arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle; 1840 arg.gssd_context_verifier = gssd_context_verifier; 1841 1842 arg.conf_req_flag = conf_req_flag; 1843 1844 arg.qop_req = qop_req; 1845 1846 arg.input_message_buffer.GSS_BUFFER_T_len = 1847 (uint_t)input_message_buffer->length; 1848 1849 arg.input_message_buffer.GSS_BUFFER_T_val = 1850 (char *)input_message_buffer->value; 1851 1852 /* call the remote procedure */ 1853 1854 bzero((caddr_t)&res, sizeof (res)); 1855 if (gss_seal_1(&arg, &res, clnt) != RPC_SUCCESS) { 1856 1857 /* 1858 * if the RPC call times out, null out all return arguments, set 1859 * minor_status to its maximum value, and return GSS_S_FAILURE 1860 */ 1861 1862 if (minor_status != NULL) 1863 *minor_status = DEFAULT_MINOR_STAT; 1864 if (conf_state != NULL) 1865 *conf_state = 0; 1866 if (output_message_buffer != NULL) 1867 output_message_buffer->length = 0; 1868 1869 killgssd_handle(clnt); 1870 GSSLOG0(1, "kgss_seal: RPC call times out\n"); 1871 return (GSS_S_FAILURE); 1872 } 1873 1874 /* copy the rpc results into the return arguments */ 1875 1876 if (minor_status != NULL) 1877 *minor_status = res.minor_status; 1878 1879 if (conf_state != NULL) 1880 *conf_state = res.conf_state; 1881 1882 if (output_message_buffer != NULL) { 1883 output_message_buffer->length = 1884 res.output_message_buffer.GSS_BUFFER_T_len; 1885 1886 output_message_buffer->value = 1887 (void *) MALLOC(output_message_buffer->length); 1888 (void) memcpy(output_message_buffer->value, 1889 res.output_message_buffer.GSS_BUFFER_T_val, 1890 output_message_buffer->length); 1891 } 1892 1893 /* 1894 * free the memory allocated for the results and return with the status 1895 * received in the rpc call 1896 */ 1897 1898 clnt_freeres(clnt, xdr_gss_seal_res, (caddr_t)&res); 1899 killgssd_handle(clnt); 1900 return (res.status); 1901 } 1902 1903 /*ARGSUSED*/ 1904 OM_uint32 1905 kgss_seal(OM_uint32 *minor_status, 1906 const gss_ctx_id_t context_handle, 1907 int conf_req_flag, 1908 int qop_req, 1909 const gss_buffer_t input_message_buffer, 1910 int *conf_state, 1911 gss_buffer_t output_message_buffer) 1912 1913 { 1914 if (context_handle == GSS_C_NO_CONTEXT) 1915 return (GSS_S_FAILURE); 1916 return (KGSS_SEAL(minor_status, context_handle, 1917 conf_req_flag, qop_req, 1918 input_message_buffer, conf_state, 1919 output_message_buffer)); 1920 } 1921 1922 /*ARGSUSED*/ 1923 static OM_uint32 1924 kgss_unseal_wrapped(void *private, 1925 OM_uint32 *minor_status, 1926 const gss_ctx_id_t ctx_handle, 1927 const gss_buffer_t input_message_buffer, 1928 gss_buffer_t output_message_buffer, 1929 int *conf_state, 1930 int *qop_state, 1931 OM_uint32 gssd_context_verifier) 1932 { 1933 CLIENT *clnt; 1934 1935 gss_unseal_arg arg; 1936 gss_unseal_res res; 1937 gssd_ctx_id_t context_handle; 1938 1939 context_handle = (gssd_ctx_id_t)KCTX_TO_GSSD_CTX(ctx_handle); 1940 1941 /* get the client handle to GSSD */ 1942 1943 if ((clnt = getgssd_handle()) == NULL) { 1944 GSSLOG(1, "kgss_unseal: can't connect to server on %s\n", 1945 server); 1946 return (GSS_S_FAILURE); 1947 } 1948 1949 /* copy the procedure arguments into the rpc arg parameter */ 1950 1951 arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gss_ctx_id_t); 1952 arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle; 1953 1954 arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t); 1955 arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle; 1956 arg.gssd_context_verifier = gssd_context_verifier; 1957 1958 arg.input_message_buffer.GSS_BUFFER_T_len = 1959 (uint_t)input_message_buffer->length; 1960 1961 arg.input_message_buffer.GSS_BUFFER_T_val = 1962 (char *)input_message_buffer->value; 1963 1964 /* call the remote procedure */ 1965 1966 bzero((caddr_t)&res, sizeof (res)); 1967 if (gss_unseal_1(&arg, &res, clnt) != RPC_SUCCESS) { 1968 1969 /* 1970 * if the RPC call times out, null out all return arguments, set 1971 * minor_status to its maximum value, and return GSS_S_FAILURE 1972 */ 1973 1974 if (minor_status != NULL) 1975 *minor_status = DEFAULT_MINOR_STAT; 1976 if (output_message_buffer != NULL) 1977 output_message_buffer->length = 0; 1978 if (conf_state != NULL) 1979 *conf_state = 0; 1980 if (qop_state != NULL) 1981 *qop_state = 0; 1982 1983 killgssd_handle(clnt); 1984 GSSLOG0(1, "kgss_unseal: RPC call times out\n"); 1985 return (GSS_S_FAILURE); 1986 } 1987 1988 /* copy the rpc results into the return arguments */ 1989 1990 if (minor_status != NULL) 1991 *minor_status = res.minor_status; 1992 1993 if (output_message_buffer != NULL) { 1994 output_message_buffer->length = 1995 res.output_message_buffer.GSS_BUFFER_T_len; 1996 1997 output_message_buffer->value = 1998 (void *) MALLOC(output_message_buffer->length); 1999 (void) memcpy(output_message_buffer->value, 2000 res.output_message_buffer.GSS_BUFFER_T_val, 2001 output_message_buffer->length); 2002 } 2003 2004 if (conf_state != NULL) 2005 *conf_state = res.conf_state; 2006 2007 if (qop_state != NULL) 2008 *qop_state = res.qop_state; 2009 2010 /* 2011 * free the memory allocated for the results and return with the 2012 * status received in the rpc call 2013 */ 2014 2015 clnt_freeres(clnt, xdr_gss_unseal_res, (caddr_t)&res); 2016 killgssd_handle(clnt); 2017 return (res.status); 2018 } 2019 2020 OM_uint32 2021 kgss_unseal(OM_uint32 *minor_status, 2022 const gss_ctx_id_t context_handle, 2023 const gss_buffer_t input_message_buffer, 2024 const gss_buffer_t output_message_buffer, 2025 int *conf_state, 2026 int *qop_state) 2027 { 2028 2029 if (context_handle == GSS_C_NO_CONTEXT) 2030 return (GSS_S_FAILURE); 2031 2032 return (KGSS_UNSEAL(minor_status, context_handle, input_message_buffer, 2033 output_message_buffer, conf_state, qop_state)); 2034 } 2035 2036 /* EXPORT DELETE END */ 2037 2038 OM_uint32 2039 kgss_display_status(minor_status, 2040 status_value, 2041 status_type, 2042 mech_type, 2043 message_context, 2044 status_string, 2045 uid) 2046 OM_uint32 *minor_status; 2047 OM_uint32 status_value; 2048 int status_type; 2049 const gss_OID mech_type; 2050 int *message_context; 2051 gss_buffer_t status_string; 2052 uid_t uid; 2053 { 2054 CLIENT *clnt; 2055 2056 gss_display_status_arg arg; 2057 gss_display_status_res res; 2058 2059 /* get the client handle to GSSD */ 2060 2061 if ((clnt = getgssd_handle()) == NULL) { 2062 GSSLOG(1, "kgss_display_status: can't connect to server on %s\n", 2063 server); 2064 return (GSS_S_FAILURE); 2065 } 2066 2067 /* copy the procedure arguments into the rpc arg parameter */ 2068 2069 arg.uid = (OM_uint32) uid; 2070 2071 arg.status_value = status_value; 2072 arg.status_type = status_type; 2073 2074 arg.mech_type.GSS_OID_len = (uint_t)(mech_type != GSS_C_NULL_OID ? 2075 mech_type->length : 0); 2076 arg.mech_type.GSS_OID_val = (char *)(mech_type != GSS_C_NULL_OID ? 2077 mech_type->elements : 0); 2078 2079 arg.message_context = *message_context; 2080 2081 /* call the remote procedure */ 2082 2083 if (message_context != NULL) 2084 *message_context = 0; 2085 if (status_string != NULL) { 2086 status_string->length = 0; 2087 status_string->value = NULL; 2088 } 2089 2090 bzero((caddr_t)&res, sizeof (res)); 2091 if (gss_display_status_1(&arg, &res, clnt) != RPC_SUCCESS) { 2092 2093 /* 2094 * if the RPC call times out, null out all return arguments, set 2095 * minor_status to its maximum value, and return GSS_S_FAILURE 2096 */ 2097 2098 if (minor_status != NULL) 2099 *minor_status = DEFAULT_MINOR_STAT; 2100 2101 killgssd_handle(clnt); 2102 GSSLOG0(1, "kgss_display_status: RPC call time out\n"); 2103 return (GSS_S_FAILURE); 2104 } 2105 2106 2107 /* now process the results and pass them back to the caller */ 2108 2109 if (res.status == GSS_S_COMPLETE) { 2110 if (minor_status != NULL) 2111 *minor_status = res.minor_status; 2112 if (message_context != NULL) 2113 *message_context = res.message_context; 2114 if (status_string != NULL) { 2115 status_string->length = 2116 (size_t)res.status_string.GSS_BUFFER_T_len; 2117 status_string->value = 2118 (void *) MALLOC(status_string->length); 2119 (void) memcpy(status_string->value, 2120 res.status_string.GSS_BUFFER_T_val, 2121 status_string->length); 2122 } 2123 } 2124 2125 clnt_freeres(clnt, xdr_gss_display_status_res, (caddr_t)&res); 2126 killgssd_handle(clnt); 2127 return (res.status); 2128 } 2129 2130 /*ARGSUSED*/ 2131 OM_uint32 2132 kgss_indicate_mechs(minor_status, 2133 mech_set, 2134 uid) 2135 OM_uint32 *minor_status; 2136 gss_OID_set *mech_set; 2137 uid_t uid; 2138 { 2139 CLIENT *clnt; 2140 void *arg; 2141 gss_indicate_mechs_res res; 2142 int i; 2143 2144 /* get the client handle to GSSD */ 2145 2146 if ((clnt = getgssd_handle()) == NULL) { 2147 GSSLOG(1, "kgss_indicate_mechs: can't connect to server on %s\n", 2148 server); 2149 return (GSS_S_FAILURE); 2150 } 2151 2152 bzero((caddr_t)&res, sizeof (res)); 2153 if (gss_indicate_mechs_1(&arg, &res, clnt) != RPC_SUCCESS) { 2154 2155 /* 2156 * if the RPC call times out, null out all return arguments, set 2157 * minor_status to its maximum value, and return GSS_S_FAILURE 2158 */ 2159 2160 if (minor_status != NULL) 2161 *minor_status = DEFAULT_MINOR_STAT; 2162 if (mech_set != NULL) 2163 *mech_set = NULL; 2164 2165 killgssd_handle(clnt); 2166 GSSLOG0(1, "kgss_indicate_mechs: RPC call times out\n"); 2167 return (GSS_S_FAILURE); 2168 } 2169 2170 /* copy the rpc results into the return arguments */ 2171 2172 if (minor_status != NULL) 2173 *minor_status = res.minor_status; 2174 2175 if (mech_set != NULL) { 2176 *mech_set = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc)); 2177 (*mech_set)->count = res.mech_set.GSS_OID_SET_len; 2178 (*mech_set)->elements = (void *) 2179 MALLOC ((*mech_set)->count * sizeof (gss_OID_desc)); 2180 for (i = 0; i < (*mech_set)->count; i++) { 2181 (*mech_set)->elements[i].length = 2182 res.mech_set.GSS_OID_SET_val[i].GSS_OID_len; 2183 (*mech_set)->elements[i].elements = (void *) 2184 MALLOC ((*mech_set)->elements[i].length); 2185 (void) memcpy((*mech_set)->elements[i].elements, 2186 res.mech_set.GSS_OID_SET_val[i].GSS_OID_val, 2187 (*mech_set)->elements[i].length); 2188 } 2189 } 2190 2191 /* 2192 * free the memory allocated for the results and return with the status 2193 * received in the rpc call 2194 */ 2195 2196 clnt_freeres(clnt, xdr_gss_indicate_mechs_res, (caddr_t)&res); 2197 killgssd_handle(clnt); 2198 return (res.status); 2199 } 2200 2201 2202 OM_uint32 2203 kgss_inquire_cred_wrapped(minor_status, 2204 cred_handle, 2205 gssd_cred_verifier, 2206 name, 2207 lifetime, 2208 cred_usage, 2209 mechanisms, 2210 uid) 2211 OM_uint32 *minor_status; 2212 const gssd_cred_id_t cred_handle; 2213 OM_uint32 gssd_cred_verifier; 2214 gss_name_t *name; 2215 OM_uint32 *lifetime; 2216 int *cred_usage; 2217 gss_OID_set *mechanisms; 2218 uid_t uid; 2219 { 2220 CLIENT *clnt; 2221 2222 OM_uint32 minor_status_temp; 2223 gss_buffer_desc external_name; 2224 gss_OID_desc name_type; 2225 int i; 2226 2227 gss_inquire_cred_arg arg; 2228 gss_inquire_cred_res res; 2229 2230 /* 2231 * NULL the params here once 2232 * If there are errors then we won't 2233 * have to do it for every error 2234 * case 2235 */ 2236 if (minor_status != NULL) 2237 *minor_status = DEFAULT_MINOR_STAT; 2238 if (name != NULL) 2239 *name = NULL; 2240 if (lifetime != NULL) 2241 *lifetime = 0; 2242 if (cred_usage != NULL) 2243 *cred_usage = 0; 2244 if (mechanisms != NULL) 2245 *mechanisms = NULL; 2246 2247 /* get the client handle to GSSD */ 2248 2249 if ((clnt = getgssd_handle()) == NULL) { 2250 GSSLOG(1, "kgss_inquire_cred: can't connect to server on %s\n", 2251 server); 2252 return (GSS_S_FAILURE); 2253 } 2254 2255 2256 /* copy the procedure arguments into the rpc arg parameter */ 2257 2258 arg.uid = (OM_uint32) uid; 2259 2260 arg.cred_handle.GSS_CRED_ID_T_len = 2261 cred_handle == (gssd_cred_id_t)GSS_C_NO_CREDENTIAL ? 2262 0 : (uint_t)sizeof (gssd_cred_id_t); 2263 arg.cred_handle.GSS_CRED_ID_T_val = (char *)&cred_handle; 2264 arg.gssd_cred_verifier = gssd_cred_verifier; 2265 2266 /* call the remote procedure */ 2267 2268 bzero((caddr_t)&res, sizeof (res)); 2269 if (gss_inquire_cred_1(&arg, &res, clnt) != RPC_SUCCESS) { 2270 2271 /* 2272 * if the RPC call times out 2273 * kill the handle and return GSS_S_FAILURE 2274 * the parameters have been set to NULL already 2275 */ 2276 2277 killgssd_handle(clnt); 2278 GSSLOG0(1, "kgss_inquire_cred: RPC call times out\n"); 2279 return (GSS_S_FAILURE); 2280 } 2281 2282 /* copy the rpc results into the return arguments */ 2283 2284 if (minor_status != NULL) 2285 *minor_status = res.minor_status; 2286 2287 /* convert name from external to internal format */ 2288 2289 if (name != NULL) { 2290 external_name.length = res.name.GSS_BUFFER_T_len; 2291 external_name.value = res.name.GSS_BUFFER_T_val; 2292 2293 /* 2294 * we can pass a pointer to res structure 2295 * since gss_import_name treats the name_type 2296 * parameter as read only and performs a copy 2297 */ 2298 2299 name_type.length = res.name_type.GSS_OID_len; 2300 name_type.elements = (void *)res.name_type.GSS_OID_val; 2301 2302 if (gss_import_name(&minor_status_temp, &external_name, 2303 &name_type, name) != GSS_S_COMPLETE) { 2304 2305 *minor_status = (OM_uint32) minor_status_temp; 2306 clnt_freeres(clnt, xdr_gss_inquire_cred_res, 2307 (caddr_t)&res); 2308 killgssd_handle(clnt); 2309 GSSLOG0(1, "kgss_inquire_cred: import name fails\n"); 2310 return ((OM_uint32) GSS_S_FAILURE); 2311 } 2312 } 2313 2314 if (lifetime != NULL) 2315 *lifetime = res.lifetime; 2316 2317 if (cred_usage != NULL) 2318 *cred_usage = res.cred_usage; 2319 2320 if (res.status == GSS_S_COMPLETE && 2321 res.mechanisms.GSS_OID_SET_len != 0 && 2322 mechanisms != NULL) { 2323 *mechanisms = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc)); 2324 (*mechanisms)->count = 2325 (int)res.mechanisms.GSS_OID_SET_len; 2326 (*mechanisms)->elements = (gss_OID) 2327 MALLOC(sizeof (gss_OID_desc) * (*mechanisms)->count); 2328 2329 for (i = 0; i < (*mechanisms)->count; i++) { 2330 (*mechanisms)->elements[i].length = (OM_uint32) 2331 res.mechanisms.GSS_OID_SET_val[i].GSS_OID_len; 2332 (*mechanisms)->elements[i].elements = 2333 (void *) MALLOC((*mechanisms)->elements[i].length); 2334 (void) memcpy((*mechanisms)->elements[i].elements, 2335 res.mechanisms.GSS_OID_SET_val[i].GSS_OID_val, 2336 (*mechanisms)->elements[i].length); 2337 } 2338 } else { 2339 if (res.status == GSS_S_COMPLETE && 2340 mechanisms != NULL) 2341 (*mechanisms) = NULL; 2342 } 2343 /* 2344 * free the memory allocated for the results and return with the status 2345 * received in the rpc call 2346 */ 2347 2348 clnt_freeres(clnt, xdr_gss_inquire_cred_res, (caddr_t)&res); 2349 killgssd_handle(clnt); 2350 return (res.status); 2351 2352 } 2353 2354 OM_uint32 2355 kgss_inquire_cred(minor_status, 2356 cred_handle, 2357 name, 2358 lifetime, 2359 cred_usage, 2360 mechanisms, 2361 uid) 2362 OM_uint32 *minor_status; 2363 const gss_cred_id_t cred_handle; 2364 gss_name_t *name; 2365 OM_uint32 *lifetime; 2366 int *cred_usage; 2367 gss_OID_set * mechanisms; 2368 uid_t uid; 2369 { 2370 2371 OM_uint32 gssd_cred_verifier; 2372 OM_uint32 gssd_cred_handle; 2373 2374 gssd_cred_verifier = KCRED_TO_CREDV(cred_handle); 2375 gssd_cred_handle = KCRED_TO_CRED(cred_handle); 2376 2377 return (kgss_inquire_cred_wrapped(minor_status, 2378 gssd_cred_handle, gssd_cred_verifier, 2379 name, lifetime, cred_usage, mechanisms, uid)); 2380 } 2381 2382 OM_uint32 2383 kgss_inquire_cred_by_mech_wrapped(minor_status, 2384 cred_handle, 2385 gssd_cred_verifier, 2386 mech_type, 2387 uid) 2388 OM_uint32 *minor_status; 2389 gssd_cred_id_t cred_handle; 2390 OM_uint32 gssd_cred_verifier; 2391 gss_OID mech_type; 2392 uid_t uid; 2393 { 2394 CLIENT *clnt; 2395 2396 gss_inquire_cred_by_mech_arg arg; 2397 gss_inquire_cred_by_mech_res res; 2398 2399 /* get the client handle to GSSD */ 2400 2401 if ((clnt = getgssd_handle()) == NULL) { 2402 GSSLOG(1, "kgss_inquire_cred: can't connect to server on %s\n", 2403 server); 2404 return (GSS_S_FAILURE); 2405 } 2406 2407 2408 /* copy the procedure arguments into the rpc arg parameter */ 2409 2410 arg.uid = (OM_uint32) uid; 2411 2412 arg.cred_handle.GSS_CRED_ID_T_len = 2413 cred_handle == (gssd_cred_id_t)GSS_C_NO_CREDENTIAL ? 2414 0 : (uint_t)sizeof (gssd_cred_id_t); 2415 arg.cred_handle.GSS_CRED_ID_T_val = (char *)&cred_handle; 2416 arg.gssd_cred_verifier = gssd_cred_verifier; 2417 2418 arg.mech_type.GSS_OID_len = 2419 (uint_t)(mech_type != GSS_C_NULL_OID ? 2420 mech_type->length : 0); 2421 arg.mech_type.GSS_OID_val = 2422 (char *)(mech_type != GSS_C_NULL_OID ? 2423 mech_type->elements : 0); 2424 /* call the remote procedure */ 2425 2426 bzero((caddr_t)&res, sizeof (res)); 2427 if (gss_inquire_cred_by_mech_1(&arg, &res, clnt) != RPC_SUCCESS) { 2428 2429 /* 2430 * if the RPC call times out, null out all return arguments, set 2431 * minor_status to its maximum value, and return GSS_S_FAILURE 2432 */ 2433 2434 if (minor_status != NULL) 2435 *minor_status = DEFAULT_MINOR_STAT; 2436 killgssd_handle(clnt); 2437 GSSLOG0(1, "kgss_inquire_cred: RPC call times out\n"); 2438 return (GSS_S_FAILURE); 2439 } 2440 2441 /* copy the rpc results into the return arguments */ 2442 2443 if (minor_status != NULL) 2444 *minor_status = res.minor_status; 2445 2446 clnt_freeres(clnt, xdr_gss_inquire_cred_by_mech_res, (caddr_t)&res); 2447 killgssd_handle(clnt); 2448 return (res.status); 2449 2450 } 2451 2452 OM_uint32 2453 kgss_inquire_cred_by_mech(minor_status, 2454 cred_handle, 2455 mech_type, 2456 uid) 2457 OM_uint32 *minor_status; 2458 gss_cred_id_t cred_handle; 2459 gss_OID mech_type; 2460 uid_t uid; 2461 { 2462 2463 OM_uint32 gssd_cred_verifier; 2464 OM_uint32 gssd_cred_handle; 2465 2466 gssd_cred_verifier = KCRED_TO_CREDV(cred_handle); 2467 gssd_cred_handle = KCRED_TO_CRED(cred_handle); 2468 2469 return (kgss_inquire_cred_by_mech_wrapped(minor_status, 2470 gssd_cred_handle, gssd_cred_verifier, 2471 mech_type, uid)); 2472 } 2473 2474 OM_uint32 2475 kgsscred_expname_to_unix_cred(expName, uidOut, gidOut, gids, gidsLen, uid) 2476 const gss_buffer_t expName; 2477 uid_t *uidOut; 2478 gid_t *gidOut; 2479 gid_t *gids[]; 2480 int *gidsLen; 2481 uid_t uid; 2482 { 2483 CLIENT *clnt; 2484 gsscred_expname_to_unix_cred_arg args; 2485 gsscred_expname_to_unix_cred_res res; 2486 2487 /* check input/output parameters */ 2488 if (expName == NULL || expName->value == NULL) 2489 return (GSS_S_CALL_INACCESSIBLE_READ); 2490 2491 if (uidOut == NULL) 2492 return (GSS_S_CALL_INACCESSIBLE_WRITE); 2493 2494 /* NULL out output parameters */ 2495 *uidOut = UID_NOBODY; 2496 if (gidsLen) 2497 *gidsLen = 0; 2498 2499 if (gids) 2500 *gids = NULL; 2501 2502 /* get the client handle to gssd */ 2503 if ((clnt = getgssd_handle()) == NULL) 2504 { 2505 GSSLOG(1, "kgsscred_expname_to_unix_cred:" 2506 " can't connect to server on %s\n", server); 2507 return (GSS_S_FAILURE); 2508 } 2509 2510 /* copy the procedure arguments */ 2511 args.uid = uid; 2512 args.expname.GSS_BUFFER_T_val = expName->value; 2513 args.expname.GSS_BUFFER_T_len = expName->length; 2514 2515 /* null out the return buffer and call the remote proc */ 2516 bzero(&res, sizeof (res)); 2517 2518 if (gsscred_expname_to_unix_cred_1(&args, &res, clnt) != RPC_SUCCESS) 2519 { 2520 killgssd_handle(clnt); 2521 GSSLOG0(1, 2522 "kgsscred_expname_to_unix_cred: RPC call times out\n"); 2523 return (GSS_S_FAILURE); 2524 } 2525 2526 /* copy the results into the result parameters */ 2527 if (res.major == GSS_S_COMPLETE) 2528 { 2529 *uidOut = res.uid; 2530 if (gidOut) 2531 *gidOut = res.gid; 2532 if (gids && gidsLen) 2533 { 2534 *gids = res.gids.GSSCRED_GIDS_val; 2535 *gidsLen = res.gids.GSSCRED_GIDS_len; 2536 res.gids.GSSCRED_GIDS_val = NULL; 2537 res.gids.GSSCRED_GIDS_len = 0; 2538 } 2539 } 2540 2541 /* free RPC results */ 2542 clnt_freeres(clnt, xdr_gsscred_expname_to_unix_cred_res, (caddr_t)&res); 2543 killgssd_handle(clnt); 2544 2545 return (res.major); 2546 } /* kgsscred_expname_to_unix_cred */ 2547 2548 OM_uint32 2549 kgsscred_name_to_unix_cred(intName, mechType, uidOut, gidOut, gids, 2550 gidsLen, uid) 2551 const gss_name_t intName; 2552 const gss_OID mechType; 2553 uid_t *uidOut; 2554 gid_t *gidOut; 2555 gid_t *gids[]; 2556 int *gidsLen; 2557 uid_t uid; 2558 { 2559 CLIENT *clnt; 2560 gsscred_name_to_unix_cred_arg args; 2561 gsscred_name_to_unix_cred_res res; 2562 OM_uint32 major, minor; 2563 gss_OID nameOid; 2564 gss_buffer_desc flatName = GSS_C_EMPTY_BUFFER; 2565 2566 /* check the input/output parameters */ 2567 if (intName == NULL || mechType == NULL) 2568 return (GSS_S_CALL_INACCESSIBLE_READ); 2569 2570 if (uidOut == NULL) 2571 return (GSS_S_CALL_INACCESSIBLE_WRITE); 2572 2573 /* NULL out the output parameters */ 2574 *uidOut = UID_NOBODY; 2575 if (gids) 2576 *gids = NULL; 2577 2578 if (gidsLen) 2579 *gidsLen = 0; 2580 2581 /* get the client handle to gssd */ 2582 if ((clnt = getgssd_handle()) == NULL) 2583 { 2584 GSSLOG(1, 2585 "kgsscred_name_to_unix_cred: can't connect to server %s\n", 2586 server); 2587 return (GSS_S_FAILURE); 2588 } 2589 2590 /* convert the name to flat representation */ 2591 if ((major = gss_display_name(&minor, intName, &flatName, &nameOid)) 2592 != GSS_S_COMPLETE) 2593 { 2594 killgssd_handle(clnt); 2595 GSSLOG0(1, "kgsscred_name_to_unix_cred: display name failed\n"); 2596 return (major); 2597 } 2598 2599 /* set the rpc parameters */ 2600 args.uid = uid; 2601 args.pname.GSS_BUFFER_T_len = flatName.length; 2602 args.pname.GSS_BUFFER_T_val = flatName.value; 2603 args.name_type.GSS_OID_len = nameOid->length; 2604 args.name_type.GSS_OID_val = nameOid->elements; 2605 args.mech_type.GSS_OID_len = mechType->length; 2606 args.mech_type.GSS_OID_val = mechType->elements; 2607 2608 /* call the remote procedure */ 2609 bzero(&res, sizeof (res)); 2610 if (gsscred_name_to_unix_cred_1(&args, &res, clnt) != RPC_SUCCESS) { 2611 killgssd_handle(clnt); 2612 (void) gss_release_buffer(&minor, &flatName); 2613 GSSLOG0(1, "kgsscred_name_to_unix_cred: RPC call times out\n"); 2614 return (GSS_S_FAILURE); 2615 } 2616 2617 /* delete the flat name buffer */ 2618 (void) gss_release_buffer(&minor, &flatName); 2619 2620 /* copy the output parameters on output */ 2621 if (res.major == GSS_S_COMPLETE) { 2622 *uidOut = res.uid; 2623 2624 if (gidOut) 2625 *gidOut = res.gid; 2626 if (gids && gidsLen) { 2627 *gids = res.gids.GSSCRED_GIDS_val; 2628 *gidsLen = res.gids.GSSCRED_GIDS_len; 2629 res.gids.GSSCRED_GIDS_val = NULL; 2630 res.gids.GSSCRED_GIDS_len = 0; 2631 } 2632 } 2633 2634 /* delete RPC allocated memory */ 2635 clnt_freeres(clnt, xdr_gsscred_name_to_unix_cred_res, (caddr_t)&res); 2636 killgssd_handle(clnt); 2637 2638 return (res.major); 2639 } /* kgsscred_name_to_unix_cred */ 2640 2641 OM_uint32 2642 kgss_get_group_info(puid, gidOut, gids, gidsLen, uid) 2643 const uid_t puid; 2644 gid_t *gidOut; 2645 gid_t *gids[]; 2646 int *gidsLen; 2647 uid_t uid; 2648 { 2649 CLIENT *clnt; 2650 gss_get_group_info_arg args; 2651 gss_get_group_info_res res; 2652 2653 2654 /* check the output parameters */ 2655 if (gidOut == NULL || gids == NULL || gidsLen == NULL) 2656 return (GSS_S_CALL_INACCESSIBLE_WRITE); 2657 2658 /* get the client GSSD handle */ 2659 if ((clnt = getgssd_handle()) == NULL) { 2660 GSSLOG(1, 2661 "kgss_get_group_info: can't connect to server on %s\n", 2662 server); 2663 return (GSS_S_FAILURE); 2664 } 2665 2666 /* set the input parameters */ 2667 args.uid = uid; 2668 args.puid = puid; 2669 2670 /* call the remote procedure */ 2671 bzero(&res, sizeof (res)); 2672 if (gss_get_group_info_1(&args, &res, clnt) != RPC_SUCCESS) { 2673 killgssd_handle(clnt); 2674 GSSLOG0(1, "kgss_get_group_info: RPC call times out\n"); 2675 return (GSS_S_FAILURE); 2676 } 2677 2678 /* copy the results */ 2679 if (res.major == GSS_S_COMPLETE) { 2680 *gidOut = res.gid; 2681 *gids = res.gids.GSSCRED_GIDS_val; 2682 *gidsLen = res.gids.GSSCRED_GIDS_len; 2683 res.gids.GSSCRED_GIDS_val = NULL; 2684 res.gids.GSSCRED_GIDS_len = 0; 2685 } 2686 2687 /* no results to free */ 2688 killgssd_handle(clnt); 2689 2690 return (res.major); 2691 } /* kgss_get_group_info */ 2692 2693 static char * 2694 kgss_get_kmod(gss_OID mech_oid) 2695 { 2696 CLIENT *clnt; 2697 gss_get_kmod_arg args; 2698 gss_get_kmod_res res; 2699 2700 2701 /* get the client GSSD handle */ 2702 if ((clnt = getgssd_handle()) == NULL) { 2703 GSSLOG(1, "kgss_get_kmod: can't connect to server on %s\n", 2704 server); 2705 return (NULL); 2706 } 2707 2708 /* set the input parameters */ 2709 args.mech_oid.GSS_OID_len = mech_oid->length; 2710 args.mech_oid.GSS_OID_val = mech_oid->elements; 2711 2712 /* call the remote procedure */ 2713 bzero(&res, sizeof (res)); 2714 if (gss_get_kmod_1(&args, &res, clnt) != RPC_SUCCESS) { 2715 killgssd_handle(clnt); 2716 GSSLOG0(1, "gss_get_kmod_1: RPC call times out\n"); 2717 return (NULL); 2718 } 2719 /* no results to free */ 2720 killgssd_handle(clnt); 2721 2722 if (res.module_follow == TRUE) { 2723 return (res.gss_get_kmod_res_u.modname); 2724 } else 2725 return (NULL); 2726 } /* kgss_get_kmod */ 2727 2728 static gss_mechanism kgss_mech_head; 2729 static gss_mechanism kgss_mech_tail; 2730 kmutex_t __kgss_mech_lock; 2731 2732 /* 2733 * See if there is kernel mechanism module, and if so, attempt to 2734 * load it and reset the pointer (gss_mechanism) to the sign/seal/etc. 2735 * entry points to that of the kernel module. 2736 */ 2737 static void 2738 __kgss_reset_mech(gss_mechanism *mechp, gss_OID mech_oid) 2739 { 2740 gss_mechanism mech; 2741 char *kmod; 2742 2743 /* 2744 * We can search the list without a mutex, becuase the list never 2745 * shrinks and we always add to the end. 2746 */ 2747 mech = __kgss_get_mechanism(mech_oid); 2748 if (mech) { 2749 *mechp = mech; 2750 return; 2751 } 2752 2753 /* 2754 * Get the module name from the kernel. 2755 */ 2756 kmod = kgss_get_kmod(mech_oid); 2757 2758 if (kmod) { 2759 extern int modload(const char *, const char *); 2760 if (modload("misc/kgss", kmod) < 0) { 2761 /* 2762 * Modload of 'kmod' failed, so log an 2763 * appropriate comment 2764 */ 2765 cmn_err(CE_NOTE, "kgss_reset_mech: Algorithm modload " 2766 "(%s) failed. Userland gssd will now handle " 2767 "all GSSAPI calls, which may result in " 2768 "reduced performance.\n", kmod); 2769 }; 2770 2771 /* 2772 * Allocated in the XDR routine called by gss_get_kmod_1(). 2773 */ 2774 FREE(kmod, strlen(kmod)+1); 2775 2776 mech = __kgss_get_mechanism(mech_oid); 2777 if (mech) { 2778 *mechp = mech; 2779 } 2780 2781 /* 2782 * If for some reason the module load didn't take, 2783 * we return anyway and hope that the next context 2784 * creation succeeds. 2785 */ 2786 return; 2787 } 2788 2789 2790 /* 2791 * No kernel module, so enter this mech oid into the list 2792 * using the default sign/seal/etc. operations that upcall to 2793 * gssd. 2794 */ 2795 mutex_enter(&__kgss_mech_lock); 2796 mech = __kgss_get_mechanism(mech_oid); 2797 if (mech) { 2798 mutex_exit(&__kgss_mech_lock); 2799 *mechp = mech; 2800 return; 2801 } 2802 2803 /* 2804 * Allocate space for the mechanism entry. 2805 */ 2806 mech = kmem_zalloc(sizeof (struct gss_config), KM_SLEEP); 2807 2808 /* 2809 * Copy basic information from default mechanism struct. 2810 */ 2811 *mech = default_gc; 2812 2813 /* 2814 * Record the real mech OID. 2815 */ 2816 mech->mech_type.length = mech_oid->length; 2817 mech->mech_type.elements = MALLOC(mech_oid->length); 2818 bcopy(mech_oid->elements, mech->mech_type.elements, mech_oid->length); 2819 2820 /* 2821 * Add it to the table. 2822 */ 2823 __kgss_add_mechanism(mech); 2824 mutex_exit(&__kgss_mech_lock); 2825 *mechp = mech; 2826 } 2827 2828 /* 2829 * Called with __kgss_mech_lock held. 2830 */ 2831 void 2832 __kgss_add_mechanism(gss_mechanism mech) 2833 { 2834 gss_mechanism tmp; 2835 2836 tmp = kgss_mech_tail; 2837 kgss_mech_tail = mech; 2838 2839 if (tmp != NULL) 2840 tmp->next = mech; 2841 2842 if (kgss_mech_head == NULL) 2843 kgss_mech_head = mech; 2844 } 2845 2846 /* 2847 * given the mechs_array and a mechanism OID, return the 2848 * pointer to the mechanism, or NULL if that mechanism is 2849 * not supported. 2850 */ 2851 gss_mechanism 2852 __kgss_get_mechanism(gss_OID type) 2853 { 2854 gss_mechanism mech; 2855 2856 mech = kgss_mech_head; 2857 2858 /* 2859 * Note that a reader can scan this list without the mutex held. 2860 * This is safe because we always append, and never shrink the list. 2861 * Moreover, the entry is fully initialized before it is ever 2862 * added to the list. 2863 */ 2864 while (mech != NULL) { 2865 if ((mech->mech_type.length == type->length) && 2866 (bcmp(mech->mech_type.elements, type->elements, 2867 type->length) == 0)) 2868 return (mech); 2869 2870 mech = mech->next; 2871 } 2872 return (NULL); 2873 } 2874