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