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