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