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