1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * GSSAPI library stub module for gssd. 30 */ 31 32 #include <mechglueP.h> 33 #include "gssd_prot.h" 34 #include <rpc/rpc.h> 35 36 #include <sys/systm.h> 37 #include <sys/types.h> 38 #include <sys/cmn_err.h> 39 #include <sys/kmem.h> 40 #include <gssapi/kgssapi_defs.h> 41 #include <sys/debug.h> 42 43 #ifdef GSSDEBUG 44 /* 45 * Kernel kgssd module debugging aid. The global variable "gss_log" 46 * is a bit mask which allows various types of debugging messages 47 * to be printed out. 48 * 49 * gss_log & 1 will cause actual failures to be printed. 50 * gss_log & 2 will cause informational messages to be 51 * printed on the client side of kgssd. 52 * gss_log & 4 will cause informational messages to be 53 * printed on the server side of kgssd. 54 * gss_log & 8 will cause informational messages to be 55 * printed on both client and server side of kgssd. 56 */ 57 58 uint_t gss_log = 1; 59 60 #endif /* GSSDEBUG */ 61 62 #ifdef DEBUG 63 extern void prom_printf(); 64 #endif 65 66 char *server = "localhost"; 67 68 static OM_uint32 kgss_sign_wrapped(void *, OM_uint32 *, gss_ctx_id_t, int, 69 gss_buffer_t, gss_buffer_t, OM_uint32); 70 71 static OM_uint32 kgss_verify_wrapped(void *, OM_uint32 *, gss_ctx_id_t, 72 gss_buffer_t, gss_buffer_t, int *qop_state, OM_uint32); 73 74 /* EXPORT DELETE START */ 75 static OM_uint32 kgss_seal_wrapped(void *, OM_uint32 *, gss_ctx_id_t, 76 int, int, gss_buffer_t, int *, gss_buffer_t, OM_uint32); 77 78 static OM_uint32 kgss_unseal_wrapped(void *, OM_uint32 *, gss_ctx_id_t, 79 gss_buffer_t, gss_buffer_t, int *conf_state, int *qop_state, 80 OM_uint32); 81 /* EXPORT DELETE END */ 82 83 static OM_uint32 kgss_delete_sec_context_wrapped(void *, OM_uint32 *, 84 gssd_ctx_id_t *, gss_buffer_t, OM_uint32); 85 86 static void __kgss_reset_mech(gss_mechanism *, gss_OID); 87 88 #define DEFAULT_MINOR_STAT ((OM_uint32) ~0) 89 90 OM_uint32 91 kgss_acquire_cred_wrapped(minor_status, 92 desired_name, 93 time_req, 94 desired_mechs, 95 cred_usage, 96 output_cred_handle, 97 actual_mechs, 98 time_rec, 99 uid, 100 gssd_cred_verifier) 101 OM_uint32 *minor_status; 102 const gss_name_t desired_name; 103 OM_uint32 time_req; 104 const gss_OID_set desired_mechs; 105 int cred_usage; 106 gssd_cred_id_t *output_cred_handle; 107 gss_OID_set *actual_mechs; 108 OM_uint32 *time_rec; 109 uid_t uid; 110 OM_uint32 *gssd_cred_verifier; 111 { 112 CLIENT *clnt; 113 114 OM_uint32 minor_status_temp; 115 gss_buffer_desc external_name; 116 gss_OID name_type; 117 enum clnt_stat client_stat; 118 int i; 119 120 gss_acquire_cred_arg arg; 121 gss_acquire_cred_res res; 122 123 /* get the client handle to GSSD */ 124 125 if ((clnt = getgssd_handle()) == NULL) { 126 GSSLOG(1, "kgss_acquire_cred: can't connect to server on %s\n", 127 server); 128 return (GSS_S_FAILURE); 129 } 130 131 /* convert the desired name from internal to external format */ 132 133 if (gss_display_name(&minor_status_temp, desired_name, &external_name, 134 &name_type) != GSS_S_COMPLETE) { 135 136 *minor_status = (OM_uint32) minor_status_temp; 137 killgssd_handle(clnt); 138 GSSLOG0(1, "kgss_acquire_cred: display name failed\n"); 139 return ((OM_uint32) GSS_S_FAILURE); 140 } 141 142 143 /* copy the procedure arguments into the rpc arg parameter */ 144 145 arg.uid = (OM_uint32) uid; 146 147 arg.desired_name.GSS_BUFFER_T_len = (uint_t)external_name.length; 148 arg.desired_name.GSS_BUFFER_T_val = (char *)external_name.value; 149 150 arg.name_type.GSS_OID_len = 151 name_type == GSS_C_NULL_OID ? 152 0 : (uint_t)name_type->length; 153 154 arg.name_type.GSS_OID_val = 155 name_type == GSS_C_NULL_OID ? 156 (char *)NULL : (char *)name_type->elements; 157 158 arg.time_req = time_req; 159 160 if (desired_mechs != GSS_C_NULL_OID_SET) { 161 arg.desired_mechs.GSS_OID_SET_len = 162 (uint_t)desired_mechs->count; 163 arg.desired_mechs.GSS_OID_SET_val = (GSS_OID *) 164 MALLOC(sizeof (GSS_OID) * desired_mechs->count); 165 166 for (i = 0; i < desired_mechs->count; i++) { 167 arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_len = 168 (uint_t)desired_mechs->elements[i].length; 169 arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val = 170 (char *)MALLOC(desired_mechs->elements[i].length); 171 (void) memcpy( 172 arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val, 173 desired_mechs->elements[i].elements, 174 desired_mechs->elements[i].length); 175 } 176 } else 177 arg.desired_mechs.GSS_OID_SET_len = 0; 178 179 arg.cred_usage = cred_usage; 180 181 /* call the remote procedure */ 182 183 bzero((caddr_t)&res, sizeof (res)); 184 client_stat = gss_acquire_cred_1(&arg, &res, clnt); 185 186 (void) gss_release_buffer(&minor_status_temp, &external_name); 187 if (desired_mechs != GSS_C_NULL_OID_SET) { 188 for (i = 0; i < desired_mechs->count; i++) 189 FREE(arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val, 190 arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_len); 191 FREE(arg.desired_mechs.GSS_OID_SET_val, 192 arg.desired_mechs.GSS_OID_SET_len * sizeof (GSS_OID)); 193 } 194 195 if (client_stat != RPC_SUCCESS) { 196 197 /* 198 * if the RPC call times out, null out all return arguments, 199 * set minor_status to its maximum value, and return 200 * GSS_S_FAILURE 201 */ 202 203 if (minor_status != NULL) 204 *minor_status = DEFAULT_MINOR_STAT; 205 if (output_cred_handle != NULL) 206 *output_cred_handle = NULL; 207 if (actual_mechs != NULL) 208 *actual_mechs = NULL; 209 if (time_rec != NULL) 210 *time_rec = 0; 211 212 killgssd_handle(clnt); 213 GSSLOG0(1, "kgss_acquire_cred: RPC call times out\n"); 214 return (GSS_S_FAILURE); 215 } 216 217 /* copy the rpc results into the return arguments */ 218 219 if (minor_status != NULL) 220 *minor_status = res.minor_status; 221 222 if (output_cred_handle != NULL && 223 (res.status == GSS_S_COMPLETE)) { 224 *output_cred_handle = 225 *((gssd_cred_id_t *)res.output_cred_handle.GSS_CRED_ID_T_val); 226 *gssd_cred_verifier = res.gssd_cred_verifier; 227 } 228 229 if (res.status == GSS_S_COMPLETE && 230 res.actual_mechs.GSS_OID_SET_len != 0 && 231 actual_mechs != NULL) { 232 *actual_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc)); 233 (*actual_mechs)->count = 234 (int)res.actual_mechs.GSS_OID_SET_len; 235 (*actual_mechs)->elements = (gss_OID) 236 MALLOC(sizeof (gss_OID_desc) * (*actual_mechs)->count); 237 238 for (i = 0; i < (*actual_mechs)->count; i++) { 239 (*actual_mechs)->elements[i].length = (OM_uint32) 240 res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_len; 241 (*actual_mechs)->elements[i].elements = 242 (void *) MALLOC((*actual_mechs)->elements[i].length); 243 (void) memcpy((*actual_mechs)->elements[i].elements, 244 res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_val, 245 (*actual_mechs)->elements[i].length); 246 } 247 } else { 248 if (res.status == GSS_S_COMPLETE && 249 actual_mechs != NULL) 250 (*actual_mechs) = NULL; 251 } 252 253 if (time_rec != NULL) 254 *time_rec = res.time_rec; 255 256 /* 257 * free the memory allocated for the results and return with the status 258 * received in the rpc call 259 */ 260 261 clnt_freeres(clnt, xdr_gss_acquire_cred_res, (caddr_t)&res); 262 killgssd_handle(clnt); 263 return (res.status); 264 265 } 266 267 OM_uint32 268 kgss_acquire_cred(minor_status, 269 desired_name, 270 time_req, 271 desired_mechs, 272 cred_usage, 273 output_cred_handle, 274 actual_mechs, 275 time_rec, 276 uid) 277 OM_uint32 *minor_status; 278 const gss_name_t desired_name; 279 OM_uint32 time_req; 280 const gss_OID_set desired_mechs; 281 int cred_usage; 282 gss_cred_id_t *output_cred_handle; 283 gss_OID_set *actual_mechs; 284 OM_uint32 *time_rec; 285 uid_t uid; 286 { 287 288 OM_uint32 err; 289 struct kgss_cred *kcred; 290 291 kcred = KGSS_CRED_ALLOC(); 292 *output_cred_handle = (gss_cred_id_t)kcred; 293 err = kgss_acquire_cred_wrapped(minor_status, desired_name, time_req, 294 desired_mechs, cred_usage, &kcred->gssd_cred, actual_mechs, 295 time_rec, uid, &kcred->gssd_cred_verifier); 296 if (GSS_ERROR(err)) { 297 KGSS_CRED_FREE(kcred); 298 *output_cred_handle = GSS_C_NO_CREDENTIAL; 299 } 300 return (err); 301 } 302 303 OM_uint32 304 kgss_add_cred_wrapped(minor_status, 305 input_cred_handle, 306 gssd_cred_verifier, 307 desired_name, 308 desired_mech_type, 309 cred_usage, 310 initiator_time_req, 311 acceptor_time_req, 312 actual_mechs, 313 initiator_time_rec, 314 acceptor_time_rec, 315 uid) 316 OM_uint32 *minor_status; 317 gssd_cred_id_t input_cred_handle; 318 OM_uint32 gssd_cred_verifier; 319 gss_name_t desired_name; 320 gss_OID desired_mech_type; 321 int cred_usage; 322 int initiator_time_req; 323 int acceptor_time_req; 324 gss_OID_set *actual_mechs; 325 OM_uint32 *initiator_time_rec; 326 OM_uint32 *acceptor_time_rec; 327 uid_t uid; 328 { 329 CLIENT *clnt; 330 331 OM_uint32 minor_status_temp; 332 gss_buffer_desc external_name; 333 gss_OID name_type; 334 int i; 335 336 gss_add_cred_arg arg; 337 gss_add_cred_res res; 338 339 340 /* 341 * NULL the params here once 342 * If there are errors then we won't 343 * have to do it for every error 344 * case 345 */ 346 347 if (minor_status != NULL) 348 *minor_status = DEFAULT_MINOR_STAT; 349 if (actual_mechs != NULL) 350 *actual_mechs = NULL; 351 if (initiator_time_rec != NULL) 352 *initiator_time_rec = 0; 353 if (acceptor_time_rec != NULL) 354 *acceptor_time_rec = 0; 355 /* get the client handle to GSSD */ 356 357 if ((clnt = getgssd_handle()) == NULL) { 358 GSSLOG(1, "kgss_add_cred: can't connect to server on %s\n", 359 server); 360 return (GSS_S_FAILURE); 361 } 362 363 364 /* convert the desired name from internal to external format */ 365 366 if (gss_display_name(&minor_status_temp, desired_name, &external_name, 367 &name_type) != GSS_S_COMPLETE) { 368 369 *minor_status = (OM_uint32) minor_status_temp; 370 killgssd_handle(clnt); 371 GSSLOG0(1, "kgss_acquire_cred: display name failed\n"); 372 return ((OM_uint32) GSS_S_FAILURE); 373 } 374 375 376 /* copy the procedure arguments into the rpc arg parameter */ 377 378 arg.uid = (OM_uint32)uid; 379 arg.input_cred_handle.GSS_CRED_ID_T_len = 380 input_cred_handle == 381 (gssd_cred_id_t)GSS_C_NO_CREDENTIAL ? 382 0 : (uint_t)sizeof (gssd_cred_id_t); 383 arg.input_cred_handle.GSS_CRED_ID_T_val = (char *)&input_cred_handle; 384 arg.gssd_cred_verifier = gssd_cred_verifier; 385 arg.desired_name.GSS_BUFFER_T_len = (uint_t)external_name.length; 386 arg.desired_name.GSS_BUFFER_T_val = (char *)external_name.value; 387 arg.name_type.GSS_OID_len = 388 name_type == GSS_C_NULL_OID ? 389 0 : (uint_t)name_type->length; 390 arg.name_type.GSS_OID_val = 391 name_type == GSS_C_NULL_OID ? 392 (char *)NULL : (char *)name_type->elements; 393 394 arg.desired_mech_type.GSS_OID_len = 395 (uint_t)(desired_mech_type != GSS_C_NULL_OID ? 396 desired_mech_type->length : 0); 397 arg.desired_mech_type.GSS_OID_val = 398 (char *)(desired_mech_type != GSS_C_NULL_OID ? 399 desired_mech_type->elements : 0); 400 arg.cred_usage = cred_usage; 401 arg.initiator_time_req = initiator_time_req; 402 arg.acceptor_time_req = acceptor_time_req; 403 404 /* call the remote procedure */ 405 406 bzero((caddr_t)&res, sizeof (res)); 407 if (gss_add_cred_1(&arg, &res, clnt) != RPC_SUCCESS) { 408 409 /* 410 * if the RPC call times out, null out all return arguments, 411 * set minor_status to its maximum value, and return 412 * GSS_S_FAILURE 413 */ 414 415 killgssd_handle(clnt); 416 (void) gss_release_buffer(&minor_status_temp, &external_name); 417 GSSLOG0(1, "kgss_add_cred: RPC call times out\n"); 418 return (GSS_S_FAILURE); 419 } 420 421 /* free the allocated memory for the flattened name */ 422 423 (void) gss_release_buffer(&minor_status_temp, &external_name); 424 425 /* copy the rpc results into the return arguments */ 426 427 if (minor_status != NULL) 428 *minor_status = res.minor_status; 429 430 if (res.status == GSS_S_COMPLETE && 431 res.actual_mechs.GSS_OID_SET_len != 0 && 432 actual_mechs != NULL) { 433 *actual_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc)); 434 (*actual_mechs)->count = 435 (int)res.actual_mechs.GSS_OID_SET_len; 436 (*actual_mechs)->elements = (gss_OID) 437 MALLOC(sizeof (gss_OID_desc) * (*actual_mechs)->count); 438 439 for (i = 0; i < (*actual_mechs)->count; i++) { 440 (*actual_mechs)->elements[i].length = (OM_uint32) 441 res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_len; 442 (*actual_mechs)->elements[i].elements = 443 (void *) MALLOC((*actual_mechs)->elements[i].length); 444 (void) memcpy((*actual_mechs)->elements[i].elements, 445 res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_val, 446 (*actual_mechs)->elements[i].length); 447 } 448 } else { 449 if (res.status == GSS_S_COMPLETE && actual_mechs != NULL) 450 (*actual_mechs) = NULL; 451 } 452 if (initiator_time_rec != NULL) 453 *initiator_time_rec = res.acceptor_time_rec; 454 if (acceptor_time_rec != NULL) 455 *acceptor_time_rec = res.acceptor_time_rec; 456 457 /* 458 * free the memory allocated for the results and return with the status 459 * received in the rpc call 460 */ 461 462 clnt_freeres(clnt, xdr_gss_add_cred_res, (caddr_t)&res); 463 killgssd_handle(clnt); 464 return (res.status); 465 466 } 467 468 OM_uint32 469 kgss_add_cred(minor_status, 470 input_cred_handle, 471 desired_name, 472 desired_mech_type, 473 cred_usage, 474 initiator_time_req, 475 acceptor_time_req, 476 actual_mechs, 477 initiator_time_rec, 478 acceptor_time_rec, 479 uid) 480 OM_uint32 *minor_status; 481 gss_cred_id_t input_cred_handle; 482 gss_name_t desired_name; 483 gss_OID desired_mech_type; 484 int cred_usage; 485 int initiator_time_req; 486 int acceptor_time_req; 487 gss_OID_set *actual_mechs; 488 OM_uint32 *initiator_time_rec; 489 OM_uint32 *acceptor_time_rec; 490 uid_t uid; 491 { 492 493 OM_uint32 err; 494 OM_uint32 gssd_cred_verifier; 495 gssd_cred_id_t gssd_input_cred_handle; 496 497 if (input_cred_handle != GSS_C_NO_CREDENTIAL) { 498 gssd_cred_verifier = KCRED_TO_CREDV(input_cred_handle); 499 gssd_input_cred_handle = KCRED_TO_CRED(input_cred_handle); 500 } else 501 gssd_input_cred_handle = (gssd_cred_id_t)GSS_C_NO_CREDENTIAL; 502 503 err = kgss_add_cred_wrapped(minor_status, gssd_input_cred_handle, 504 gssd_cred_verifier, desired_name, desired_mech_type, 505 cred_usage, initiator_time_req, acceptor_time_req, 506 actual_mechs, initiator_time_rec, 507 acceptor_time_rec, uid); 508 return (err); 509 } 510 511 512 OM_uint32 513 kgss_release_cred_wrapped(minor_status, 514 cred_handle, 515 uid, 516 gssd_cred_verifier) 517 OM_uint32 *minor_status; 518 gssd_cred_id_t *cred_handle; 519 uid_t uid; 520 OM_uint32 gssd_cred_verifier; 521 { 522 CLIENT *clnt; 523 524 gss_release_cred_arg arg; 525 gss_release_cred_res res; 526 527 528 /* get the client handle to GSSD */ 529 530 if ((clnt = getgssd_handle()) == NULL) { 531 GSSLOG(1, "kgss_release_cred: can't connect to server on %s\n", 532 server); 533 return (GSS_S_FAILURE); 534 } 535 536 /* copy the procedure arguments into the rpc arg parameter */ 537 538 arg.uid = (OM_uint32)uid; 539 arg.gssd_cred_verifier = gssd_cred_verifier; 540 541 if (cred_handle != NULL) { 542 arg.cred_handle.GSS_CRED_ID_T_len = 543 (uint_t)sizeof (gssd_cred_id_t); 544 arg.cred_handle.GSS_CRED_ID_T_val = (char *)cred_handle; 545 } else 546 arg.cred_handle.GSS_CRED_ID_T_len = 0; 547 548 /* call the remote procedure */ 549 550 bzero((caddr_t)&res, sizeof (res)); 551 if (gss_release_cred_1(&arg, &res, clnt) != RPC_SUCCESS) { 552 553 /* 554 * if the RPC call times out, null out all return arguments, set 555 * minor_status to its maximum value, and return GSS_S_FAILURE 556 */ 557 558 if (minor_status != NULL) 559 *minor_status = DEFAULT_MINOR_STAT; 560 if (cred_handle != NULL) 561 *cred_handle = NULL; 562 563 killgssd_handle(clnt); 564 GSSLOG0(1, "kgss_release_cred: RPC call times out\n"); 565 return (GSS_S_FAILURE); 566 } 567 568 /* if the release succeeded, null out the cred_handle */ 569 570 if (res.status == GSS_S_COMPLETE && cred_handle != NULL) 571 *cred_handle = NULL; 572 573 /* copy the rpc results into the return arguments */ 574 575 if (minor_status != NULL) 576 *minor_status = res.minor_status; 577 578 /* return with status returned in rpc call */ 579 580 killgssd_handle(clnt); 581 582 return (res.status); 583 584 } 585 586 OM_uint32 587 kgss_release_cred(minor_status, 588 cred_handle, 589 uid) 590 OM_uint32 *minor_status; 591 gss_cred_id_t *cred_handle; 592 uid_t uid; 593 594 { 595 596 OM_uint32 err; 597 struct kgss_cred *kcred; 598 599 if (*cred_handle == GSS_C_NO_CREDENTIAL) 600 return (GSS_S_COMPLETE); 601 else 602 kcred = KCRED_TO_KGSS_CRED(*cred_handle); 603 604 err = kgss_release_cred_wrapped(minor_status, &kcred->gssd_cred, 605 uid, kcred->gssd_cred_verifier); 606 KGSS_CRED_FREE(kcred); 607 *cred_handle = GSS_C_NO_CREDENTIAL; 608 return (err); 609 } 610 611 static OM_uint32 612 kgss_init_sec_context_wrapped( 613 OM_uint32 *minor_status, 614 const gssd_cred_id_t claimant_cred_handle, 615 OM_uint32 gssd_cred_verifier, 616 gssd_ctx_id_t *context_handle, 617 OM_uint32 *gssd_context_verifier, 618 const gss_name_t target_name, 619 const gss_OID mech_type, 620 int req_flags, 621 OM_uint32 time_req, 622 const gss_channel_bindings_t input_chan_bindings, 623 const gss_buffer_t input_token, 624 gss_OID *actual_mech_type, 625 gss_buffer_t output_token, 626 int *ret_flags, 627 OM_uint32 *time_rec, 628 uid_t uid) 629 { 630 CLIENT *clnt; 631 632 OM_uint32 minor_status_temp; 633 gss_buffer_desc external_name; 634 gss_OID name_type; 635 636 gss_init_sec_context_arg arg; 637 gss_init_sec_context_res res; 638 639 /* get the client handle to GSSD */ 640 641 if ((clnt = getgssd_handle()) == NULL) { 642 GSSLOG(1, 643 "kgss_init_sec_context: can't connect to server on %s\n", 644 server); 645 return (GSS_S_FAILURE); 646 } 647 648 /* convert the target name from internal to external format */ 649 650 if (gss_display_name(&minor_status_temp, target_name, 651 &external_name, &name_type) != GSS_S_COMPLETE) { 652 653 *minor_status = (OM_uint32) minor_status_temp; 654 killgssd_handle(clnt); 655 GSSLOG0(1, "kgss_init_sec_context: can't display name\n"); 656 return ((OM_uint32) GSS_S_FAILURE); 657 } 658 659 660 /* copy the procedure arguments into the rpc arg parameter */ 661 662 arg.uid = (OM_uint32)uid; 663 664 arg.context_handle.GSS_CTX_ID_T_len = 665 *context_handle == (gssd_ctx_id_t)GSS_C_NO_CONTEXT ? 666 0 : (uint_t)sizeof (gssd_ctx_id_t); 667 arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle; 668 669 arg.gssd_context_verifier = *gssd_context_verifier; 670 671 arg.claimant_cred_handle.GSS_CRED_ID_T_len = 672 claimant_cred_handle == (gssd_cred_id_t)GSS_C_NO_CREDENTIAL ? 673 0 : (uint_t)sizeof (gssd_cred_id_t); 674 arg.claimant_cred_handle.GSS_CRED_ID_T_val = 675 (char *)&claimant_cred_handle; 676 arg.gssd_cred_verifier = gssd_cred_verifier; 677 678 arg.target_name.GSS_BUFFER_T_len = (uint_t)external_name.length; 679 arg.target_name.GSS_BUFFER_T_val = (char *)external_name.value; 680 681 arg.name_type.GSS_OID_len = 682 name_type == GSS_C_NULL_OID ? 683 0 : (uint_t)name_type->length; 684 685 arg.name_type.GSS_OID_val = 686 name_type == GSS_C_NULL_OID ? 687 (char *)NULL : (char *)name_type->elements; 688 689 arg.mech_type.GSS_OID_len = (uint_t)(mech_type != GSS_C_NULL_OID ? 690 mech_type->length : 0); 691 arg.mech_type.GSS_OID_val = (char *)(mech_type != GSS_C_NULL_OID ? 692 mech_type->elements : 0); 693 694 arg.req_flags = req_flags; 695 696 arg.time_req = time_req; 697 698 if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) { 699 arg.input_chan_bindings.present = YES; 700 arg.input_chan_bindings.initiator_addrtype = 701 input_chan_bindings->initiator_addrtype; 702 arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = 703 (uint_t)input_chan_bindings->initiator_address.length; 704 arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = 705 (void *)input_chan_bindings->initiator_address.value; 706 arg.input_chan_bindings.acceptor_addrtype = 707 input_chan_bindings->acceptor_addrtype; 708 arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = 709 (uint_t)input_chan_bindings->acceptor_address.length; 710 arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = 711 (void *)input_chan_bindings->acceptor_address.value; 712 arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = 713 (uint_t)input_chan_bindings->application_data.length; 714 arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = 715 (void *)input_chan_bindings->application_data.value; 716 } else { 717 arg.input_chan_bindings.present = NO; 718 arg.input_chan_bindings.initiator_addrtype = 0; 719 arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = 0; 720 arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = 0; 721 arg.input_chan_bindings.acceptor_addrtype = 0; 722 arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = 0; 723 arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = 0; 724 arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = 0; 725 arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = 0; 726 } 727 728 arg.input_token.GSS_BUFFER_T_len = 729 (uint_t)(input_token != GSS_C_NO_BUFFER ? 730 input_token->length : 0); 731 arg.input_token.GSS_BUFFER_T_val = 732 (char *)(input_token != GSS_C_NO_BUFFER ? 733 input_token->value : 0); 734 735 /* call the remote procedure */ 736 737 bzero((caddr_t)&res, sizeof (res)); 738 if (gss_init_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) { 739 740 /* 741 * if the RPC call times out, null out all return arguments, set 742 * minor_status to its maximum value, and return GSS_S_FAILURE 743 */ 744 745 if (minor_status != NULL) 746 *minor_status = DEFAULT_MINOR_STAT; 747 if (actual_mech_type != NULL) 748 *actual_mech_type = NULL; 749 if (output_token != NULL) 750 output_token->length = 0; 751 if (ret_flags != NULL) 752 *ret_flags = 0; 753 if (time_rec != NULL) 754 *time_rec = 0; 755 756 killgssd_handle(clnt); 757 (void) gss_release_buffer(&minor_status_temp, &external_name); 758 GSSLOG0(1, "kgss_init_sec_context: RPC call times out\n"); 759 return (GSS_S_FAILURE); 760 } 761 762 /* free the allocated memory for the flattened name */ 763 764 (void) gss_release_buffer(&minor_status_temp, &external_name); 765 766 if (minor_status != NULL) 767 *minor_status = res.minor_status; 768 769 /* if the call was successful, copy out the results */ 770 if (res.status == (OM_uint32) GSS_S_COMPLETE || 771 res.status == (OM_uint32) GSS_S_CONTINUE_NEEDED) { 772 /* 773 * if the return code is GSS_S_CONTINUE_NEEDED 774 * ignore all return parameters except for 775 * status codes, output token and context handle. 776 */ 777 *context_handle = 778 *((gssd_ctx_id_t *) 779 res.context_handle.GSS_CTX_ID_T_val); 780 *gssd_context_verifier = res.gssd_context_verifier; 781 782 if (output_token != NULL) { 783 output_token->length = 784 (size_t)res.output_token.GSS_BUFFER_T_len; 785 output_token->value = 786 (void *)MALLOC(output_token->length); 787 (void) memcpy(output_token->value, 788 res.output_token.GSS_BUFFER_T_val, 789 output_token->length); 790 } 791 792 if (res.status == GSS_S_COMPLETE) { 793 if (actual_mech_type != NULL) { 794 *actual_mech_type = 795 (gss_OID) MALLOC(sizeof (gss_OID_desc)); 796 (*actual_mech_type)->length = 797 (OM_UINT32) 798 res.actual_mech_type.GSS_OID_len; 799 (*actual_mech_type)->elements = 800 (void *) 801 MALLOC((*actual_mech_type)->length); 802 (void) memcpy((*actual_mech_type)->elements, 803 (void *) 804 res.actual_mech_type.GSS_OID_val, 805 (*actual_mech_type)->length); 806 } 807 808 809 if (ret_flags != NULL) 810 *ret_flags = res.ret_flags; 811 812 if (time_rec != NULL) 813 *time_rec = res.time_rec; 814 } 815 } 816 817 /* 818 * free the memory allocated for the results and return with the status 819 * received in the rpc call 820 */ 821 822 clnt_freeres(clnt, xdr_gss_init_sec_context_res, (caddr_t)&res); 823 killgssd_handle(clnt); 824 return (res.status); 825 826 } 827 828 static struct gss_config default_gc = { 829 { 0, NULL}, 830 NULL, 831 NULL, 832 0, 833 /* EXPORT DELETE START */ /* CRYPT DELETE START */ 834 kgss_unseal_wrapped, 835 /* EXPORT DELETE END */ /* CRYPT DELETE END */ 836 NULL, /* kgss_delete_sec_context_wrapped */ 837 /* EXPORT DELETE START */ /* CRYPT DELETE START */ 838 kgss_seal_wrapped, 839 /* EXPORT DELETE END */ /* CRYPT DELETE END */ 840 NULL, /* kgss_import_sec_context */ 841 /* EXPORT DELETE START */ 842 /* CRYPT DELETE START */ 843 #if 0 844 /* CRYPT DELETE END */ 845 kgss_seal_wrapped, 846 kgss_unseal_wrapped, 847 /* CRYPT DELETE START */ 848 #endif 849 /* CRYPT DELETE END */ 850 /* EXPORT DELETE END */ 851 kgss_sign_wrapped, 852 kgss_verify_wrapped 853 }; 854 855 void 856 kgss_free_oid(gss_OID oid) 857 { 858 FREE(oid->elements, oid->length); 859 FREE(oid, sizeof (gss_OID_desc)); 860 } 861 862 OM_uint32 863 kgss_init_sec_context( 864 OM_uint32 *minor_status, 865 const gss_cred_id_t claimant_cred_handle, 866 gss_ctx_id_t *context_handle, 867 const gss_name_t target_name, 868 const gss_OID mech_type, 869 int req_flags, 870 OM_uint32 time_req, 871 const gss_channel_bindings_t input_chan_bindings, 872 const gss_buffer_t input_token, 873 gss_OID *actual_mech_type, 874 gss_buffer_t output_token, 875 int *ret_flags, 876 OM_uint32 *time_rec, 877 uid_t uid) 878 { 879 OM_uint32 err; 880 struct kgss_ctx *kctx; 881 gss_OID amt; 882 gssd_cred_id_t gssd_cl_cred_handle; 883 OM_uint32 gssd_cred_verifier; 884 885 /* 886 * If this is an initial call, we'll need to create the 887 * wrapper struct that contains kernel state information, and 888 * a reference to the handle from gssd. 889 */ 890 if (*context_handle == GSS_C_NO_CONTEXT) { 891 kctx = KGSS_ALLOC(); 892 /* 893 * The default gss-mechanism struct as pointers to 894 * the sign/seal/verify/unseal routines that make 895 * upcalls to gssd. 896 */ 897 kctx->mech = &default_gc; 898 kctx->gssd_ctx = (gssd_ctx_id_t)GSS_C_NO_CONTEXT; 899 *context_handle = (gss_ctx_id_t)kctx; 900 } else 901 kctx = (struct kgss_ctx *)*context_handle; 902 903 if (claimant_cred_handle != GSS_C_NO_CREDENTIAL) { 904 gssd_cred_verifier = KCRED_TO_CREDV(claimant_cred_handle); 905 gssd_cl_cred_handle = KCRED_TO_CRED(claimant_cred_handle); 906 } else 907 gssd_cl_cred_handle = (gssd_cred_id_t)GSS_C_NO_CREDENTIAL; 908 909 /* 910 * We need to know the resulting mechanism oid, so allocate 911 * it if the caller won't. 912 */ 913 if (actual_mech_type == NULL) 914 actual_mech_type = &amt; 915 916 err = kgss_init_sec_context_wrapped(minor_status, gssd_cl_cred_handle, 917 gssd_cred_verifier, &kctx->gssd_ctx, &kctx->gssd_ctx_verifier, 918 target_name, mech_type, req_flags, time_req, 919 input_chan_bindings, input_token, actual_mech_type, 920 output_token, ret_flags, time_rec, uid); 921 922 if (GSS_ERROR(err)) { 923 KGSS_FREE(kctx); 924 *context_handle = GSS_C_NO_CONTEXT; 925 } else if (err == GSS_S_COMPLETE) { 926 /* 927 * Now check if there is a kernel module for this 928 * mechanism OID. If so, set the gss_mechanism structure 929 * in the wrapper context to point to the kernel mech. 930 */ 931 __kgss_reset_mech(&kctx->mech, *actual_mech_type); 932 933 /* 934 * If the mech oid was allocated for us, free it. 935 */ 936 if (&amt == actual_mech_type) { 937 kgss_free_oid(amt); 938 } 939 } 940 return (err); 941 } 942 943 static OM_uint32 944 kgss_accept_sec_context_wrapped( 945 OM_uint32 *minor_status, 946 gssd_ctx_id_t *context_handle, 947 OM_uint32 *gssd_context_verifier, 948 const gssd_cred_id_t verifier_cred_handle, 949 OM_uint32 gssd_cred_verifier, 950 const gss_buffer_t input_token, 951 const gss_channel_bindings_t input_chan_bindings, 952 gss_buffer_t src_name, 953 gss_OID *mech_type, 954 gss_buffer_t output_token, 955 int *ret_flags, 956 OM_uint32 *time_rec, 957 gss_cred_id_t *delegated_cred_handle, 958 uid_t uid) 959 { 960 CLIENT *clnt; 961 962 gss_accept_sec_context_arg arg; 963 gss_accept_sec_context_res res; 964 struct kgss_cred *kcred; 965 966 /* get the client handle to GSSD */ 967 968 if ((clnt = getgssd_handle()) == NULL) { 969 GSSLOG(1, 970 "kgss_accept_sec_context: can't connect to server on %s\n", 971 server); 972 return (GSS_S_FAILURE); 973 } 974 975 /* copy the procedure arguments into the rpc arg parameter */ 976 977 arg.uid = (OM_uint32)uid; 978 979 arg.context_handle.GSS_CTX_ID_T_len = 980 *context_handle == (gssd_ctx_id_t)GSS_C_NO_CONTEXT ? 981 0 : (uint_t)sizeof (gssd_ctx_id_t); 982 arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle; 983 arg.gssd_context_verifier = *gssd_context_verifier; 984 985 arg.verifier_cred_handle.GSS_CRED_ID_T_len = 986 verifier_cred_handle == 987 (gssd_cred_id_t)GSS_C_NO_CREDENTIAL ? 988 0 : (uint_t)sizeof (gssd_cred_id_t); 989 arg.verifier_cred_handle.GSS_CRED_ID_T_val = 990 (char *)&verifier_cred_handle; 991 arg.gssd_cred_verifier = gssd_cred_verifier; 992 993 arg.input_token_buffer.GSS_BUFFER_T_len = 994 (uint_t)(input_token != GSS_C_NO_BUFFER ? 995 input_token->length : 0); 996 arg.input_token_buffer.GSS_BUFFER_T_val = 997 (char *)(input_token != GSS_C_NO_BUFFER ? 998 input_token->value : 0); 999 1000 if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) { 1001 arg.input_chan_bindings.present = YES; 1002 arg.input_chan_bindings.initiator_addrtype = 1003 input_chan_bindings->initiator_addrtype; 1004 arg.input_chan_bindings.