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