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