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