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, &kctx->gssd_ctx, 1068 &kctx->gssd_ctx_verifier, gssd_ver_cred_handle, 1069 gssd_cred_verifier, input_token, input_chan_bindings, 1070 src_name, mech_type, output_token, ret_flags, 1071 time_rec, delegated_cred_handle, uid); 1072 1073 if (GSS_ERROR(err)) { 1074 KGSS_FREE(kctx); 1075 *context_handle = GSS_C_NO_CONTEXT; 1076 1077 } 1078 1079 return (err); 1080 } 1081 1082 OM_uint32 1083 kgss_process_context_token(minor_status, 1084 context_handle, 1085 token_buffer, 1086 uid) 1087 OM_uint32 *minor_status; 1088 gss_ctx_id_t context_handle; 1089 gss_buffer_t token_buffer; 1090 uid_t uid; 1091 { 1092 OM_uint32 gssd_context_verifier; 1093 1094 gss_process_context_token_arg arg; 1095 gss_process_context_token_res res; 1096 1097 gssd_context_verifier = KGSS_CTX_TO_GSSD_CTXV(context_handle); 1098 1099 /* get the client handle to GSSD */ 1100 1101 if ((clnt = getgssd_handle()) == NULL) { 1102 clnt_pcreateerror(server); 1103 return (GSS_S_FAILURE); 1104 } 1105 1106 /* copy the procedure arguments into the rpc arg parameter */ 1107 arg.uid = (OM_uint32) uid; 1108 1109 arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gss_ctx_id_t); 1110 arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle; 1111 arg.gssd_context_verifier = gssd_context_verifier; 1112 arg.token_buffer.GSS_BUFFER_T_len = (uint_t)token_buffer; 1113 arg.token_buffer.GSS_BUFFER_T_val = (char *)token_buffer->value; 1114 1115 /* call the remote procedure */ 1116 1117 memset(&res, 0, sizeof (res)); 1118 if (gss_process_context_token_1(&arg, &res, clnt) != RPC_SUCCESS) { 1119 1120 /* 1121 * if the RPC call times out, null out all return arguments, 1122 * set minor_status to its maximum value, and return GSS_S_FAILURE 1123 */ 1124 1125 if (minor_status != NULL) 1126 *minor_status = DEFAULT_MINOR_STAT; 1127 1128 return (GSS_S_FAILURE); 1129 } 1130 1131 /* copy the rpc results into the return arguments */ 1132 1133 if (minor_status != NULL) 1134 *minor_status = res.minor_status; 1135 1136 /* return with status returned in rpc call */ 1137 1138 return (res.status); 1139 } 1140 1141 OM_uint32 1142 kgss_delete_sec_context_wrapped(minor_status, 1143 context_handle, 1144 gssd_context_verifier, 1145 output_token) 1146 OM_uint32 *minor_status; 1147 gssd_ctx_id_t *context_handle; 1148 OM_uint32 gssd_context_verifier; 1149 gss_buffer_t output_token; 1150 { 1151 gss_delete_sec_context_arg arg; 1152 gss_delete_sec_context_res res; 1153 1154 1155 /* get the client handle to GSSD */ 1156 if ((clnt = getgssd_handle()) == NULL) { 1157 clnt_pcreateerror(server); 1158 return (GSS_S_FAILURE); 1159 } 1160 1161 /* copy the procedure arguments into the rpc arg parameter */ 1162 1163 arg.context_handle.GSS_CTX_ID_T_len = 1164 *context_handle == (OM_uint32) GSS_C_NO_CONTEXT ? 0 : 1165 (uint_t)sizeof (OM_uint32); 1166 arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle; 1167 1168 arg.gssd_context_verifier = gssd_context_verifier; 1169 1170 /* call the remote procedure */ 1171 1172 memset(&res, 0, sizeof (res)); 1173 if (gss_delete_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) { 1174 1175 /* 1176 * if the RPC call times out, null out all return arguments, 1177 * set minor_status to its max value, and return GSS_S_FAILURE 1178 */ 1179 1180 if (minor_status != NULL) 1181 *minor_status = DEFAULT_MINOR_STAT; 1182 if (context_handle != NULL) 1183 *context_handle = NULL; 1184 if (output_token != NULL) 1185 output_token->length = 0; 1186 1187 return (GSS_S_FAILURE); 1188 } 1189 1190 /* copy the rpc results into the return arguments */ 1191 1192 if (minor_status != NULL) 1193 *minor_status = res.minor_status; 1194 1195 if (res.context_handle.GSS_CTX_ID_T_len == 0) 1196 *context_handle = NULL; 1197 else 1198 /*LINTED*/ 1199 *context_handle = *((gssd_ctx_id_t *) 1200 res.context_handle.GSS_CTX_ID_T_val); 1201 1202 if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) { 1203 output_token->length = res.output_token.GSS_BUFFER_T_len; 1204 output_token->value = res.output_token.GSS_BUFFER_T_val; 1205 res.output_token.GSS_BUFFER_T_len = 0; 1206 res.output_token.GSS_BUFFER_T_val = NULL; 1207 } 1208 1209 /* 1210 * free the memory allocated for the results and return with the status 1211 * received in the rpc call 1212 */ 1213 1214 clnt_freeres(clnt, xdr_gss_delete_sec_context_res, (caddr_t)&res); 1215 return (res.status); 1216 } 1217 1218 /*ARGSUSED*/ 1219 OM_uint32 1220 kgss_delete_sec_context( 1221 OM_uint32 *minor_status, 1222 gss_ctx_id_t *context_handle, 1223 gss_buffer_t output_token) 1224 { 1225 OM_uint32 err; 1226 struct kgss_ctx *kctx; 1227 1228 if (*context_handle == GSS_C_NO_CONTEXT) { 1229 return (GSS_S_NO_CONTEXT); 1230 } else 1231 kctx = KCTX_TO_KGSS_CTX(*context_handle); 1232 1233 err = kgss_delete_sec_context_wrapped(minor_status, 1234 &kctx->gssd_ctx, kctx->gssd_ctx_verifier, 1235 output_token); 1236 1237 if (kctx->gssd_ctx != GSSD_NO_CONTEXT) 1238 err = GSS_S_FAILURE; 1239 else 1240 err = GSS_S_COMPLETE; 1241 1242 KGSS_FREE(kctx); 1243 *context_handle = GSS_C_NO_CONTEXT; 1244 return (err); 1245 } 1246 1247 /*ARGSUSED*/ 1248 OM_uint32 1249 kgss_context_time(minor_status, 1250 context_handle, 1251 time_rec, 1252 uid) 1253 OM_uint32 *minor_status; 1254 gss_ctx_id_t context_handle; 1255 OM_uint32 *time_rec; 1256 uid_t uid; 1257 { 1258 return (GSS_S_FAILURE); 1259 } 1260 1261 OM_uint32 1262 kgss_sign_wrapped(minor_status, 1263 context_handle, 1264 qop_req, 1265 message_buffer, 1266 msg_token, 1267 gssd_context_verifier) 1268 OM_uint32 *minor_status; 1269 gssd_ctx_id_t context_handle; 1270 OM_uint32 gssd_context_verifier; 1271 int qop_req; 1272 gss_buffer_t message_buffer; 1273 gss_buffer_t msg_token; 1274 { 1275 1276 gss_sign_arg arg; 1277 gss_sign_res res; 1278 1279 /* get the client handle to GSSD */ 1280 1281 if ((clnt = getgssd_handle()) == NULL) { 1282 clnt_pcreateerror(server); 1283 return (GSS_S_FAILURE); 1284 } 1285 1286 /* copy the procedure arguments into the rpc arg parameter */ 1287 1288 1289 arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t); 1290 arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle; 1291 arg.gssd_context_verifier = gssd_context_verifier; 1292 1293 arg.qop_req = qop_req; 1294 arg.message_buffer.GSS_BUFFER_T_len = (uint_t)message_buffer->length; 1295 arg.message_buffer.GSS_BUFFER_T_val = (char *)message_buffer->value; 1296 1297 /* call the remote procedure */ 1298 1299 memset(&res, 0, sizeof (res)); 1300 if (gss_sign_1(&arg, &res, clnt) != RPC_SUCCESS) { 1301 1302 /* 1303 * if the RPC call times out, null out all return arguments, 1304 * set minor_status to its maximum value, and return GSS_S_FAILURE 1305 */ 1306 1307 if (minor_status != NULL) 1308 *minor_status = DEFAULT_MINOR_STAT; 1309 if (msg_token != NULL) 1310 msg_token->length = 0; 1311 1312 return (GSS_S_FAILURE); 1313 } 1314 1315 /* copy the rpc results into the return arguments */ 1316 1317 if (minor_status != NULL) 1318 *minor_status = res.minor_status; 1319 1320 if (msg_token != NULL) { 1321 msg_token->length = res.msg_token.GSS_BUFFER_T_len; 1322 msg_token->value = (void *) MALLOC(msg_token->length); 1323 memcpy(msg_token->value, res.msg_token.GSS_BUFFER_T_val, 1324 msg_token->length); 1325 } 1326 1327 /* 1328 * free the memory allocated for the results and return with the status 1329 * received in the rpc call 1330 */ 1331 1332 clnt_freeres(clnt, xdr_gss_sign_res, (caddr_t)&res); 1333 return (res.status); 1334 } 1335 1336 OM_uint32 1337 kgss_sign( 1338 OM_uint32 *minor_status, 1339 gss_ctx_id_t context_handle, 1340 int qop_req, 1341 gss_buffer_t message_buffer, 1342 gss_buffer_t msg_token) 1343 { 1344 if (context_handle == GSS_C_NO_CONTEXT) 1345 return (GSS_S_FAILURE); 1346 1347 return (KGSS_SIGN(minor_status, 1348 context_handle, qop_req, message_buffer, 1349 msg_token)); 1350 } 1351 1352 OM_uint32 1353 kgss_verify_wrapped( 1354 minor_status, 1355 context_handle, 1356 message_buffer, 1357 token_buffer, 1358 qop_state, 1359 gssd_context_verifier) 1360 OM_uint32 *minor_status; 1361 gssd_ctx_id_t context_handle; 1362 OM_uint32 gssd_context_verifier; 1363 gss_buffer_t message_buffer; 1364 gss_buffer_t token_buffer; 1365 int *qop_state; 1366 { 1367 gss_verify_arg arg; 1368 gss_verify_res res; 1369 1370 /* get the client handle to GSSD */ 1371 1372 if ((clnt = getgssd_handle()) == NULL) { 1373 clnt_pcreateerror(server); 1374 return (GSS_S_FAILURE); 1375 } 1376 1377 /* copy the procedure arguments into the rpc arg parameter */ 1378 1379 arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t); 1380 arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle; 1381 1382 arg.gssd_context_verifier = gssd_context_verifier; 1383 1384 arg.message_buffer.GSS_BUFFER_T_len = (uint_t)message_buffer->length; 1385 arg.message_buffer.GSS_BUFFER_T_val = (char *)message_buffer->value; 1386 1387 arg.token_buffer.GSS_BUFFER_T_len = (uint_t)token_buffer->length; 1388 arg.token_buffer.GSS_BUFFER_T_val = (char *)token_buffer->value; 1389 1390 /* call the remote procedure */ 1391 1392 memset(&res, 0, sizeof (res)); 1393 if (gss_verify_1(&arg, &res, clnt) != RPC_SUCCESS) { 1394 1395 /* 1396 * if the RPC call times out, null out all return arguments, 1397 * set minor_status to its maximum value, and return GSS_S_FAILURE 1398 */ 1399 1400 if (minor_status != NULL) 1401 *minor_status = DEFAULT_MINOR_STAT; 1402 if (qop_state != NULL) 1403 *qop_state = 0; 1404 1405 return (GSS_S_FAILURE); 1406 } 1407 1408 /* copy the rpc results into the return arguments */ 1409 1410 if (minor_status != NULL) 1411 *minor_status = res.minor_status; 1412 1413 if (qop_state != NULL) 1414 *qop_state = res.qop_state; 1415 1416 /* return with status returned in rpc call */ 1417 1418 return (res.status); 1419 } 1420 1421 OM_uint32 1422 kgss_verify(OM_uint32 *minor_status, 1423 gss_ctx_id_t context_handle, 1424 gss_buffer_t message_buffer, 1425 gss_buffer_t token_buffer, 1426 int *qop_state) 1427 { 1428 if (context_handle == GSS_C_NO_CONTEXT) 1429 return (GSS_S_FAILURE); 1430 1431 return (KGSS_VERIFY(minor_status, context_handle, 1432 message_buffer, token_buffer, qop_state)); 1433 } 1434 1435 1436 OM_uint32 1437 kgss_seal_wrapped( 1438 minor_status, 1439 context_handle, 1440 conf_req_flag, 1441 qop_req, 1442 input_message_buffer, 1443 conf_state, 1444 output_message_buffer, 1445 gssd_context_verifier) 1446 1447 OM_uint32 *minor_status; 1448 gssd_ctx_id_t context_handle; 1449 OM_uint32 gssd_context_verifier; 1450 int conf_req_flag; 1451 int qop_req; 1452 gss_buffer_t input_message_buffer; 1453 int *conf_state; 1454 gss_buffer_t output_message_buffer; 1455 { 1456 gss_seal_arg arg; 1457 gss_seal_res res; 1458 1459 /* get the client handle to GSSD */ 1460 1461 if ((clnt = getgssd_handle()) == NULL) { 1462 clnt_pcreateerror(server); 1463 return (GSS_S_FAILURE); 1464 } 1465 1466 /* copy the procedure arguments into the rpc arg parameter */ 1467 1468 1469 arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t); 1470 arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle; 1471 arg.gssd_context_verifier = gssd_context_verifier; 1472 1473 arg.conf_req_flag = conf_req_flag; 1474 1475 arg.qop_req = qop_req; 1476 1477 arg.input_message_buffer.GSS_BUFFER_T_len = 1478 (uint_t)input_message_buffer->length; 1479 1480 arg.input_message_buffer.GSS_BUFFER_T_val = 1481 (char *)input_message_buffer->value; 1482 1483 /* call the remote procedure */ 1484 1485 memset(&res, 0, sizeof (res)); 1486 if (gss_seal_1(&arg, &res, clnt) != RPC_SUCCESS) { 1487 1488 /* 1489 * if the RPC call times out, null out all return arguments, 1490 * set minor_status to its maximum value, and return GSS_S_FAILURE 1491 */ 1492 1493 if (minor_status != NULL) 1494 *minor_status = DEFAULT_MINOR_STAT; 1495 if (conf_state != NULL) 1496 *conf_state = 0; 1497 if (output_message_buffer != NULL) 1498 output_message_buffer->length = 0; 1499 1500 return (GSS_S_FAILURE); 1501 } 1502 1503 /* copy the rpc results into the return arguments */ 1504 1505 if (minor_status != NULL) 1506 *minor_status = res.minor_status; 1507 1508 if (conf_state != NULL) 1509 *conf_state = res.conf_state; 1510 1511 if (output_message_buffer != NULL) { 1512 output_message_buffer->length = 1513 res.output_message_buffer.GSS_BUFFER_T_len; 1514 1515 output_message_buffer->value = 1516 (void *) MALLOC(output_message_buffer->length); 1517 memcpy(output_message_buffer->value, 1518 res.output_message_buffer.GSS_BUFFER_T_val, 1519 output_message_buffer->length); 1520 } 1521 1522 /* 1523 * free the memory allocated for the results and return with the status 1524 * received in the rpc call 1525 */ 1526 1527 clnt_freeres(clnt, xdr_gss_seal_res, (caddr_t)&res); 1528 return (res.status); 1529 } 1530 1531 OM_uint32 1532 kgss_seal(OM_uint32 *minor_status, 1533 gss_ctx_id_t context_handle, 1534 int conf_req_flag, 1535 int qop_req, 1536 gss_buffer_t input_message_buffer, 1537 int *conf_state, 1538 gss_buffer_t output_message_buffer) 1539 1540 { 1541 if (context_handle == GSS_C_NO_CONTEXT) 1542 return (GSS_S_FAILURE); 1543 1544 return (KGSS_SEAL(minor_status, context_handle, 1545 conf_req_flag, qop_req, 1546 input_message_buffer, 1547 conf_state, output_message_buffer)); 1548 } 1549 1550 OM_uint32 1551 kgss_unseal_wrapped(minor_status, 1552 context_handle, 1553 input_message_buffer, 1554 output_message_buffer, 1555 conf_state, 1556 qop_state, 1557 gssd_context_verifier) 1558 OM_uint32 *minor_status; 1559 gssd_ctx_id_t context_handle; 1560 OM_uint32 gssd_context_verifier; 1561 gss_buffer_t input_message_buffer; 1562 gss_buffer_t output_message_buffer; 1563 int *conf_state; 1564 int *qop_state; 1565 { 1566 gss_unseal_arg arg; 1567 gss_unseal_res res; 1568 1569 /* get the client handle to GSSD */ 1570 1571 if ((clnt = getgssd_handle()) == NULL) { 1572 clnt_pcreateerror(server); 1573 return (GSS_S_FAILURE); 1574 } 1575 1576 /* copy the procedure arguments into the rpc arg parameter */ 1577 1578 1579 arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t); 1580 arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle; 1581 arg.gssd_context_verifier = gssd_context_verifier; 1582 1583 arg.input_message_buffer.GSS_BUFFER_T_len = 1584 (uint_t)input_message_buffer->length; 1585 1586 arg.input_message_buffer.GSS_BUFFER_T_val = 1587 (char *)input_message_buffer->value; 1588 1589 /* call the remote procedure */ 1590 1591 memset(&res, 0, sizeof (res)); 1592 if (gss_unseal_1(&arg, &res, clnt) != RPC_SUCCESS) { 1593 1594 /* 1595 * if the RPC call times out, null out all return arguments, 1596 * set minor_status to its maximum value, and return GSS_S_FAILURE 1597 */ 1598 1599 if (minor_status != NULL) 1600 *minor_status = DEFAULT_MINOR_STAT; 1601 if (output_message_buffer != NULL) 1602 output_message_buffer->length = 0; 1603 if (conf_state != NULL) 1604 *conf_state = 0; 1605 if (qop_state != NULL) 1606 *qop_state = 0; 1607 1608 return (GSS_S_FAILURE); 1609 } 1610 1611 /* copy the rpc results into the return arguments */ 1612 1613 if (minor_status != NULL) 1614 *minor_status = res.minor_status; 1615 1616 if (output_message_buffer != NULL) { 1617 output_message_buffer->length = 1618 res.output_message_buffer.GSS_BUFFER_T_len; 1619 1620 output_message_buffer->value = 1621 (void *) MALLOC(output_message_buffer->length); 1622 memcpy(output_message_buffer->value, 1623 res.output_message_buffer.GSS_BUFFER_T_val, 1624 output_message_buffer->length); 1625 } 1626 1627 if (conf_state != NULL) 1628 *conf_state = res.conf_state; 1629 1630 if (qop_state != NULL) 1631 *qop_state = res.qop_state; 1632 1633 /* 1634 * free the memory allocated for the results and return with the status 1635 * received in the rpc call 1636 */ 1637 1638 clnt_freeres(clnt, xdr_gss_unseal_res, (caddr_t)&res); 1639 return (res.status); 1640 } 1641 1642 OM_uint32 1643 kgss_unseal(OM_uint32 *minor_status, 1644 gss_ctx_id_t context_handle, 1645 gss_buffer_t input_message_buffer, 1646 gss_buffer_t output_message_buffer, 1647 int *conf_state, 1648 int *qop_state) 1649 { 1650 if (context_handle == GSS_C_NO_CONTEXT) 1651 return (GSS_S_FAILURE); 1652 1653 return (KGSS_UNSEAL(minor_status, context_handle, 1654 input_message_buffer, output_message_buffer, 1655 conf_state, qop_state)); 1656 } 1657 1658 OM_uint32 1659 kgss_display_status(minor_status, 1660 status_value, 1661 status_type, 1662 mech_type, 1663 message_context, 1664 status_string, 1665 uid) 1666 OM_uint32 *minor_status; 1667 OM_uint32 status_value; 1668 int status_type; 1669 gss_OID mech_type; 1670 int *message_context; 1671 gss_buffer_t status_string; 1672 uid_t uid; 1673 { 1674 gss_display_status_arg arg; 1675 gss_display_status_res res; 1676 1677 /* get the client handle to GSSD */ 1678 1679 if ((clnt = getgssd_handle()) == NULL) { 1680 clnt_pcreateerror(server); 1681 return (GSS_S_FAILURE); 1682 } 1683 1684 /* copy the procedure arguments into the rpc arg parameter */ 1685 1686 arg.uid = (OM_uint32) uid; 1687 1688 arg.status_value = status_value; 1689 arg.status_type = status_type; 1690 1691 arg.mech_type.GSS_OID_len = (uint_t)(mech_type != GSS_C_NULL_OID ? 1692 mech_type->length : 0); 1693 arg.mech_type.GSS_OID_val = (char *)(mech_type != GSS_C_NULL_OID ? 1694 mech_type->elements : 0); 1695 1696 arg.message_context = *message_context; 1697 1698 /* call the remote procedure */ 1699 1700 if (message_context != NULL) 1701 *message_context = 0; 1702 if (status_string != NULL) { 1703 status_string->length = 0; 1704 status_string->value = NULL; 1705 } 1706 1707 memset(&res, 0, sizeof (res)); 1708 if (gss_display_status_1(&arg, &res, clnt) != RPC_SUCCESS) { 1709 1710 /* 1711 * if the RPC call times out, null out all return arguments, 1712 * set minor_status to its maximum value, and return GSS_S_FAILURE 1713 */ 1714 1715 if (minor_status != NULL) 1716 *minor_status = DEFAULT_MINOR_STAT; 1717 1718 return (GSS_S_FAILURE); 1719 } 1720 1721 if (minor_status != NULL) 1722 *minor_status = res.minor_status; 1723 1724 /* now process the results and pass them back to the caller */ 1725 1726 if (res.status == GSS_S_COMPLETE) { 1727 if (message_context != NULL) 1728 *message_context = res.message_context; 1729 if (status_string != NULL) { 1730 status_string->length = 1731 (size_t)res.status_string.GSS_BUFFER_T_len; 1732 status_string->value = 1733 (void *)MALLOC(status_string->length); 1734 memcpy(status_string->value, 1735 res.status_string.GSS_BUFFER_T_val, 1736 status_string->length); 1737 } 1738 } 1739 1740 clnt_freeres(clnt, xdr_gss_display_status_res, (caddr_t)&res); 1741 return (res.status); 1742 } 1743 1744 /*ARGSUSED*/ 1745 OM_uint32 1746 kgss_indicate_mechs(minor_status, 1747 mech_set, 1748 uid) 1749 OM_uint32 *minor_status; 1750 gss_OID_set *mech_set; 1751 uid_t uid; 1752 { 1753 void *arg; 1754 gss_indicate_mechs_res res; 1755 int i; 1756 1757 /* get the client handle to GSSD */ 1758 1759 if ((clnt = getgssd_handle()) == NULL) { 1760 clnt_pcreateerror(server); 1761 return (GSS_S_FAILURE); 1762 } 1763 1764 memset(&res, 0, sizeof (res)); 1765 if (gss_indicate_mechs_1(&arg, &res, clnt) != RPC_SUCCESS) { 1766 1767 /* 1768 * if the RPC call times out, null out all return arguments, 1769 * set minor_status to its maximum value, and return GSS_S_FAILURE 1770 */ 1771 1772 if (minor_status != NULL) 1773 *minor_status = DEFAULT_MINOR_STAT; 1774 if (mech_set != NULL) 1775 *mech_set = NULL; 1776 1777 return (GSS_S_FAILURE); 1778 } 1779 1780 /* copy the rpc results into the return arguments */ 1781 1782 if (minor_status != NULL) 1783 *minor_status = res.minor_status; 1784 1785 if (mech_set != NULL) { 1786 *mech_set = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc)); 1787 (*mech_set)->count = res.mech_set.GSS_OID_SET_len; 1788 (*mech_set)->elements = (void *) 1789 MALLOC ((*mech_set)->count * sizeof (gss_OID_desc)); 1790 for (i = 0; i < (*mech_set)->count; i++) { 1791 (*mech_set)->elements[i].length = 1792 res.mech_set.GSS_OID_SET_val[i].GSS_OID_len; 1793 (*mech_set)->elements[i].elements = (void *) 1794 MALLOC ((*mech_set)->elements[i].length); 1795 memcpy ((*mech_set)->elements[i].elements, 1796 res.mech_set.GSS_OID_SET_val[i].GSS_OID_val, 1797 (*mech_set)->elements[i].length); 1798 } 1799 } 1800 1801 /* 1802 * free the memory allocated for the results and return with the status 1803 * received in the rpc call 1804 */ 1805 1806 clnt_freeres(clnt, xdr_gss_indicate_mechs_res, (caddr_t)&res); 1807 return (res.status); 1808 } 1809 1810 1811 OM_uint32 1812 kgss_inquire_cred_wrapped(minor_status, 1813 cred_handle, 1814 gssd_cred_verifier, 1815 name, 1816 lifetime, 1817 cred_usage, 1818 mechanisms, 1819 uid) 1820 OM_uint32 *minor_status; 1821 gssd_cred_id_t cred_handle; 1822 OM_uint32 gssd_cred_verifier; 1823 gss_name_t *name; 1824 OM_uint32 *lifetime; 1825 int *cred_usage; 1826 gss_OID_set *mechanisms; 1827 uid_t uid; 1828 { 1829 OM_uint32 minor_status_temp; 1830 gss_buffer_desc external_name; 1831 gss_OID name_type; 1832 int i; 1833 1834 gss_inquire_cred_arg arg; 1835 gss_inquire_cred_res res; 1836 1837 /* get the client handle to GSSD */ 1838 1839 if ((clnt = getgssd_handle()) == NULL) { 1840 clnt_pcreateerror(server); 1841 return (GSS_S_FAILURE); 1842 } 1843 1844 1845 /* copy the procedure arguments into the rpc arg parameter */ 1846 1847 arg.uid = (OM_uint32) uid; 1848 1849 arg.cred_handle.GSS_CRED_ID_T_len = 1850 cred_handle == GSSD_NO_CREDENTIAL ? 1851 0 : (uint_t)sizeof (gssd_cred_id_t); 1852 arg.cred_handle.GSS_CRED_ID_T_val = (char *)&cred_handle; 1853 arg.gssd_cred_verifier = gssd_cred_verifier; 1854 1855 /* call the remote procedure */ 1856 1857 memset(&res, 0, sizeof (res)); 1858 if (gss_inquire_cred_1(&arg, &res, clnt) != RPC_SUCCESS) { 1859 1860 /* 1861 * if the RPC call times out, null out all return arguments, 1862 * set minor_status to its maximum value, and return GSS_S_FAILURE 1863 */ 1864 1865 if (minor_status != NULL) 1866 *minor_status = DEFAULT_MINOR_STAT; 1867 if (name != NULL) 1868 *name = NULL; 1869 if (lifetime != NULL) 1870 *lifetime = 0; 1871 if (cred_usage != NULL) 1872 *cred_usage = 0; 1873 if (mechanisms != NULL) 1874 *mechanisms = NULL; 1875 1876 return (GSS_S_FAILURE); 1877 } 1878 1879 /* copy the rpc results into the return arguments */ 1880 1881 if (minor_status != NULL) 1882 *minor_status = res.minor_status; 1883 1884 /* convert name from external to internal format */ 1885 1886 if (name != NULL) { 1887 external_name.length = res.name.GSS_BUFFER_T_len; 1888 external_name.value = res.name.GSS_BUFFER_T_val; 1889 1890 /* 1891 * we have to allocate a name_type descriptor and 1892 * elements storage, since gss_import_name() only 1893 * stores a pointer to the name_type info in the 1894 * union_name struct 1895 */ 1896 1897 name_type = (gss_OID) MALLOC(sizeof (gss_OID_desc)); 1898 1899 name_type->length = res.name_type.GSS_OID_len; 1900 name_type->elements = (void *) MALLOC(name_type->length); 1901 memcpy(name_type->elements, res.name_type.GSS_OID_val, 1902 name_type->length); 1903 1904 if (gss_import_name(&minor_status_temp, &external_name, 1905 name_type, name) != GSS_S_COMPLETE) { 1906 1907 *minor_status = (OM_uint32) minor_status_temp; 1908 gss_release_buffer(&minor_status_temp, &external_name); 1909 1910 clnt_freeres(clnt, xdr_gss_inquire_cred_res, 1911 (caddr_t)&res); 1912 return ((OM_uint32) GSS_S_FAILURE); 1913 } 1914 } 1915 1916 if (lifetime != NULL) 1917 *lifetime = res.lifetime; 1918 1919 if (cred_usage != NULL) 1920 *cred_usage = res.cred_usage; 1921 1922 if (mechanisms != NULL) { 1923 *mechanisms = 1924 (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc)); 1925 if (res.mechanisms.GSS_OID_SET_len != 0) { 1926 (*mechanisms)->count = 1927 (int)res.mechanisms.GSS_OID_SET_len; 1928 (*mechanisms)->elements = (gss_OID) 1929 MALLOC(sizeof (gss_OID) * (*mechanisms)->count); 1930 1931 for (i = 0; i < (*mechanisms)->count; i++) { 1932 (*mechanisms)->elements[i].length = (OM_uint32) 1933 res.mechanisms.GSS_OID_SET_val[i].GSS_OID_len; 1934 (*mechanisms)->elements[i].elements = (void *) 1935 MALLOC((*mechanisms)->elements[i].length); 1936 memcpy((*mechanisms)->elements[i].elements, 1937 res.mechanisms.GSS_OID_SET_val[i].GSS_OID_val, 1938 (*mechanisms)->elements[i].length); 1939 } 1940 } else 1941 (*mechanisms)->count = 0; 1942 } 1943 1944 /* 1945 * free the memory allocated for the results and return with the status 1946 * received in the rpc call 1947 */ 1948 1949 clnt_freeres(clnt, xdr_gss_inquire_cred_res, (caddr_t)&res); 1950 return (res.status); 1951 } 1952 1953 1954 OM_uint32 1955 kgss_inquire_cred(minor_status, 1956 cred_handle, 1957 name, 1958 lifetime, 1959 cred_usage, 1960 mechanisms, 1961 uid) 1962 OM_uint32 *minor_status; 1963 gss_cred_id_t cred_handle; 1964 gss_name_t *name; 1965 OM_uint32 *lifetime; 1966 int *cred_usage; 1967 gss_OID_set * mechanisms; 1968 uid_t uid; 1969 { 1970 1971 OM_uint32 gssd_cred_verifier; 1972 gssd_cred_id_t gssd_cred_handle; 1973 1974 gssd_cred_verifier = KCRED_TO_CREDV(cred_handle); 1975 gssd_cred_handle = KCRED_TO_CRED(cred_handle); 1976 1977 return (kgss_inquire_cred_wrapped(minor_status, 1978 gssd_cred_handle, gssd_cred_verifier, 1979 name, lifetime, cred_usage, mechanisms, uid)); 1980 } 1981 1982 1983 OM_uint32 1984 kgss_inquire_cred_by_mech_wrapped(minor_status, 1985 cred_handle, 1986 gssd_cred_verifier, 1987 mech_type, 1988 uid) 1989 OM_uint32 *minor_status; 1990 gssd_cred_id_t cred_handle; 1991 OM_uint32 gssd_cred_verifier; 1992 gss_OID mech_type; 1993 uid_t uid; 1994 { 1995 OM_uint32 minor_status_temp; 1996 1997 gss_inquire_cred_by_mech_arg arg; 1998 gss_inquire_cred_by_mech_res res; 1999 2000 /* get the client handle to GSSD */ 2001 2002 if ((clnt = getgssd_handle()) == NULL) { 2003 clnt_pcreateerror(server); 2004 return (GSS_S_FAILURE); 2005 } 2006 2007 2008 /* copy the procedure arguments into the rpc arg parameter */ 2009 2010 arg.uid = (OM_uint32) uid; 2011 2012 arg.cred_handle.GSS_CRED_ID_T_len = 2013 cred_handle == GSSD_NO_CREDENTIAL ? 2014 0 : (uint_t)sizeof (gssd_cred_id_t); 2015 arg.cred_handle.GSS_CRED_ID_T_val = (char *)&cred_handle; 2016 arg.gssd_cred_verifier = gssd_cred_verifier; 2017 2018 arg.mech_type.GSS_OID_len = 2019 (uint_t)(mech_type != GSS_C_NULL_OID ? 2020 mech_type->length : 0); 2021 arg.mech_type.GSS_OID_val = 2022 (char *)(mech_type != GSS_C_NULL_OID ? 2023 mech_type->elements : 0); 2024 /* call the remote procedure */ 2025 2026 memset(&res, 0, sizeof (res)); 2027 if (gss_inquire_cred_by_mech_1(&arg, &res, clnt) != RPC_SUCCESS) { 2028 2029 /* 2030 * if the RPC call times out, null out all return arguments, 2031 * set minor_status to its maximum value, and return GSS_S_FAILURE 2032 */ 2033 2034 if (minor_status != NULL) 2035 *minor_status = DEFAULT_MINOR_STAT; 2036 return (GSS_S_FAILURE); 2037 } 2038 2039 /* copy the rpc results into the return arguments */ 2040 2041 if (minor_status != NULL) 2042 *minor_status = res.minor_status; 2043 2044 /* convert name from external to internal format */ 2045 2046 /* 2047 * free the memory allocated for the results and return with the status 2048 * received in the rpc call 2049 */ 2050 2051 clnt_freeres(clnt, xdr_gss_inquire_cred_by_mech_res, (caddr_t)&res); 2052 return (res.status); 2053 } 2054 2055 2056 OM_uint32 2057 kgss_inquire_cred_by_mech(minor_status, 2058 cred_handle, 2059 mech_type, 2060 uid) 2061 OM_uint32 *minor_status; 2062 gss_cred_id_t cred_handle; 2063 gss_OID mech_type; 2064 uid_t uid; 2065 { 2066 2067 OM_uint32 gssd_cred_verifier; 2068 gssd_cred_id_t gssd_cred_handle; 2069 2070 gssd_cred_verifier = KCRED_TO_CREDV(cred_handle); 2071 gssd_cred_handle = KCRED_TO_CRED(cred_handle); 2072 2073 return (kgss_inquire_cred_by_mech_wrapped(minor_status, 2074 gssd_cred_handle, gssd_cred_verifier, 2075 mech_type, uid)); 2076 } 2077 2078 OM_uint32 2079 kgsscred_expname_to_unix_cred(expName, uidOut, gidOut, gids, gidsLen, uid) 2080 const gss_buffer_t expName; 2081 uid_t *uidOut; 2082 gid_t *gidOut; 2083 gid_t *gids[]; 2084 int *gidsLen; 2085 uid_t uid; 2086 { 2087 gsscred_expname_to_unix_cred_arg args; 2088 gsscred_expname_to_unix_cred_res res; 2089 2090 /* check input/output parameters */ 2091 if (expName == NULL || expName->value == NULL) 2092 return (GSS_S_CALL_INACCESSIBLE_READ); 2093 2094 if (uidOut == NULL) 2095 return (GSS_S_CALL_INACCESSIBLE_WRITE); 2096 2097 /* NULL out output parameters */ 2098 *uidOut = 0; 2099 if (gidsLen) 2100 *gidsLen = 0; 2101 2102 if (gids) 2103 *gids = NULL; 2104 2105 /* get the client handle to gssd */ 2106 if ((clnt = getgssd_handle()) == NULL) 2107 { 2108 clnt_pcreateerror(server); 2109 return (GSS_S_FAILURE); 2110 } 2111 2112 /* copy the procedure arguments */ 2113 args.uid = uid; 2114 args.expname.GSS_BUFFER_T_val = expName->value; 2115 args.expname.GSS_BUFFER_T_len = expName->length; 2116 2117 /* null out the return buffer and call the remote proc */ 2118 memset(&res, 0, sizeof (res)); 2119 2120 if (gsscred_expname_to_unix_cred_1(&args, &res, clnt) != RPC_SUCCESS) 2121 { 2122 return (GSS_S_FAILURE); 2123 } 2124 2125 /* copy the results into the result parameters */ 2126 if (res.major == GSS_S_COMPLETE) 2127 { 2128 *uidOut = res.uid; 2129 if (gidOut) 2130 *gidOut = res.gid; 2131 if (gids && gidsLen) 2132 { 2133 *gids = res.gids.GSSCRED_GIDS_val; 2134 *gidsLen = res.gids.GSSCRED_GIDS_len; 2135 res.gids.GSSCRED_GIDS_val = NULL; 2136 res.gids.GSSCRED_GIDS_len = 0; 2137 } 2138 } 2139 2140 /* free RPC results */ 2141 clnt_freeres(clnt, xdr_gsscred_expname_to_unix_cred_res, (caddr_t)&res); 2142 2143 return (res.major); 2144 } /* kgsscred_expname_to_unix_cred */ 2145 2146 OM_uint32 2147 kgsscred_name_to_unix_cred(intName, mechType, uidOut, gidOut, gids, 2148 gidsLen, uid) 2149 const gss_name_t intName; 2150 const gss_OID mechType; 2151 uid_t *uidOut; 2152 gid_t *gidOut; 2153 gid_t *gids[]; 2154 int *gidsLen; 2155 uid_t uid; 2156 { 2157 gsscred_name_to_unix_cred_arg args; 2158 gsscred_name_to_unix_cred_res res; 2159 OM_uint32 major, minor; 2160 gss_OID nameOid; 2161 gss_buffer_desc flatName = GSS_C_EMPTY_BUFFER; 2162 2163 2164 /* check the input/output parameters */ 2165 if (intName == NULL || mechType == NULL) 2166 return (GSS_S_CALL_INACCESSIBLE_READ); 2167 2168 if (uidOut == NULL) 2169 return (GSS_S_CALL_INACCESSIBLE_WRITE); 2170 2171 /* NULL out the output parameters */ 2172 *uidOut = 0; 2173 if (gids) 2174 *gids = NULL; 2175 2176 if (gidsLen) 2177 *gidsLen = 0; 2178 2179 /* get the client handle to gssd */ 2180 if ((clnt = getgssd_handle()) == NULL) 2181 { 2182 clnt_pcreateerror(server); 2183 return (GSS_S_FAILURE); 2184 } 2185 2186 /* convert the name to flat representation */ 2187 if ((major = gss_display_name(&minor, intName, &flatName, &nameOid)) 2188 != GSS_S_COMPLETE) 2189 { 2190 return (major); 2191 } 2192 2193 /* set the rpc parameters */ 2194 args.uid = uid; 2195 args.pname.GSS_BUFFER_T_len = flatName.length; 2196 args.pname.GSS_BUFFER_T_val = flatName.value; 2197 args.name_type.GSS_OID_len = nameOid->length; 2198 args.name_type.GSS_OID_val = nameOid->elements; 2199 args.mech_type.GSS_OID_len = mechType->length; 2200 args.mech_type.GSS_OID_val = mechType->elements; 2201 2202 /* call the remote procedure */ 2203 memset(&res, 0, sizeof (res)); 2204 if (gsscred_name_to_unix_cred_1(&args, &res, clnt) != RPC_SUCCESS) 2205 { 2206 gss_release_buffer(&minor, &flatName); 2207 return (GSS_S_FAILURE); 2208 } 2209 2210 gss_release_buffer(&minor, &flatName); 2211 /* copy the output parameters on output */ 2212 if (res.major == GSS_S_COMPLETE) 2213 { 2214 *uidOut = res.uid; 2215 if (gidOut) 2216 *gidOut = res.gid; 2217 if (gids && gidsLen) 2218 { 2219 *gids = res.gids.GSSCRED_GIDS_val; 2220 *gidsLen = res.gids.GSSCRED_GIDS_len; 2221 res.gids.GSSCRED_GIDS_val = NULL; 2222 res.gids.GSSCRED_GIDS_len = 0; 2223 } 2224 } 2225 2226 /* delete RPC allocated memory */ 2227 clnt_freeres(clnt, xdr_gsscred_name_to_unix_cred_res, (caddr_t)&res); 2228 2229 return (res.major); 2230 } /* kgsscred_name_to_unix_cred */ 2231 2232 OM_uint32 2233 kgss_get_group_info(puid, gidOut, gids, gidsLen, uid) 2234 const uid_t puid; 2235 gid_t *gidOut; 2236 gid_t *gids[]; 2237 int *gidsLen; 2238 uid_t uid; 2239 { 2240 gss_get_group_info_arg args; 2241 gss_get_group_info_res res; 2242 2243 2244 /* check the output parameters */ 2245 if (gidOut == NULL || gids == NULL || gidsLen == NULL) 2246 return (GSS_S_CALL_INACCESSIBLE_WRITE); 2247 2248 /* get the client GSSD handle */ 2249 if ((clnt = getgssd_handle()) == NULL) 2250 { 2251 clnt_pcreateerror(server); 2252 return (GSS_S_FAILURE); 2253 } 2254 2255 /* set the input parameters */ 2256 args.uid = uid; 2257 args.puid = puid; 2258 2259 2260 /* call the remote procedure */ 2261 memset(&res, 0, sizeof (res)); 2262 if (gss_get_group_info_1(&args, &res, clnt) != RPC_SUCCESS) 2263 { 2264 return (GSS_S_FAILURE); 2265 } 2266 2267 /* copy the results */ 2268 if (res.major == GSS_S_COMPLETE) 2269 { 2270 *gidOut = res.gid; 2271 *gids = res.gids.GSSCRED_GIDS_val; 2272 *gidsLen = res.gids.GSSCRED_GIDS_len; 2273 res.gids.GSSCRED_GIDS_val = NULL; 2274 res.gids.GSSCRED_GIDS_len = 0; 2275 } 2276 2277 /* nothing to free */ 2278 2279 return (res.major); 2280 } /* kgss_get_group_info */ 2281 2282 OM_uint32 2283 kgss_export_sec_context_wrapped(minor_status, 2284 context_handle, 2285 output_token, 2286 gssd_context_verifier) 2287 OM_uint32 *minor_status; 2288 gssd_ctx_id_t *context_handle; 2289 gss_buffer_t output_token; 2290 OM_uint32 gssd_context_verifier; 2291 { 2292 CLIENT *clnt; 2293 gss_export_sec_context_arg arg; 2294 gss_export_sec_context_res res; 2295 2296 2297 /* get the client handle to GSSD */ 2298 2299 if ((clnt = getgssd_handle()) == NULL) { 2300 clnt_pcreateerror(server); 2301 return (GSS_S_FAILURE); 2302 } 2303 2304 /* copy the procedure arguments into the rpc arg parameter */ 2305 2306 arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t); 2307 arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle; 2308 arg.gssd_context_verifier = gssd_context_verifier; 2309 2310 /* call the remote procedure */ 2311 2312 memset(&res, 0, sizeof (res)); 2313 if (gss_export_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) { 2314 2315 /* 2316 * if the RPC call times out, null out all return arguments, set minor_status 2317 * to its maximum value, and return GSS_S_FAILURE 2318 */ 2319 2320 if (minor_status != NULL) 2321 *minor_status = DEFAULT_MINOR_STAT; 2322 if (context_handle != NULL) 2323 *context_handle = NULL; 2324 if (output_token != NULL) 2325 output_token->length = 0; 2326 2327 return (GSS_S_FAILURE); 2328 } 2329 2330 /* copy the rpc results into the return arguments */ 2331 2332 if (minor_status != NULL) 2333 *minor_status = res.minor_status; 2334 2335 if (res.context_handle.GSS_CTX_ID_T_len == 0) 2336 *context_handle = NULL; 2337 else 2338 *context_handle = 2339 *((gssd_ctx_id_t *)res.context_handle.GSS_CTX_ID_T_val); 2340 2341 if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) { 2342 output_token->length = res.output_token.GSS_BUFFER_T_len; 2343 output_token->value = 2344 (void *) MALLOC(output_token->length); 2345 memcpy(output_token->value, 2346 res.output_token.GSS_BUFFER_T_val, 2347 output_token->length); 2348 } 2349 2350 /* 2351 * free the memory allocated for the results and return with the status 2352 * received in the rpc call 2353 */ 2354 2355 clnt_freeres(clnt, xdr_gss_export_sec_context_res, (caddr_t)&res); 2356 return (res.status); 2357 2358 } 2359 2360 OM_uint32 2361 kgss_export_sec_context(minor_status, 2362 context_handle, 2363 output_token) 2364 OM_uint32 *minor_status; 2365 gss_ctx_id_t *context_handle; 2366 gss_buffer_t output_token; 2367 { 2368 OM_uint32 err; 2369 struct kgss_ctx *kctx; 2370 2371 if (*context_handle == GSS_C_NO_CONTEXT) { 2372 return (GSS_S_NO_CONTEXT); 2373 } else 2374 kctx = KCTX_TO_KGSS_CTX(*context_handle); 2375 2376 err = kgss_export_sec_context_wrapped(minor_status, 2377 &kctx->gssd_ctx, output_token, 2378 kctx->gssd_ctx_verifier); 2379 2380 if (GSS_ERROR(err)) 2381 return (err); 2382 else { 2383 KGSS_FREE(kctx); 2384 *context_handle = GSS_C_NO_CONTEXT; 2385 return (err); 2386 } 2387 2388 } 2389 2390 OM_uint32 2391 kgss_import_sec_context_wrapped(minor_status, 2392 input_token, 2393 context_handle, 2394 gssd_context_verifier) 2395 OM_uint32 *minor_status; 2396 gss_buffer_t input_token; 2397 gss_ctx_id_t *context_handle; 2398 OM_uint32 gssd_context_verifier; 2399 { 2400 CLIENT *clnt; 2401 gss_import_sec_context_arg arg; 2402 gss_import_sec_context_res res; 2403 2404 2405 /* get the client handle to GSSD */ 2406 2407 if ((clnt = getgssd_handle()) == NULL) { 2408 clnt_pcreateerror(server); 2409 return (GSS_S_FAILURE); 2410 } 2411 2412 /* copy the procedure arguments into the rpc arg parameter */ 2413 arg.input_token.GSS_BUFFER_T_len = (uint_t) 2414 (input_token != GSS_C_NO_BUFFER ? input_token->length : 0); 2415 arg.input_token.GSS_BUFFER_T_val = (char *) 2416 (input_token != GSS_C_NO_BUFFER ? input_token->value : 0); 2417 arg.gssd_context_verifier = gssd_context_verifier; 2418 2419 2420 /* call the remote procedure */ 2421 2422 memset(&res, 0, sizeof (res)); 2423 if (gss_import_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) { 2424 2425 /* 2426 * if the RPC call times out, null out all return arguments, set minor_status 2427 * to its maximum value, and return GSS_S_FAILURE 2428 */ 2429 2430 if (minor_status != NULL) 2431 *minor_status = DEFAULT_MINOR_STAT; 2432 if (context_handle != NULL) 2433 *context_handle = NULL; 2434 2435 return (GSS_S_FAILURE); 2436 } 2437 2438 /* copy the rpc results into the return arguments */ 2439 2440 if (minor_status != NULL) 2441 *minor_status = res.minor_status; 2442 2443 if (res.context_handle.GSS_CTX_ID_T_len == 0) 2444 *context_handle = NULL; 2445 else 2446 *context_handle = 2447 *((gss_ctx_id_t *)res.context_handle.GSS_CTX_ID_T_val); 2448 2449 2450 /* 2451 * free the memory allocated for the results and return with the status 2452 * received in the rpc call 2453 */ 2454 2455 clnt_freeres(clnt, xdr_gss_import_sec_context_res, (caddr_t)&res); 2456 return (res.status); 2457 } 2458 2459 OM_uint32 2460 kgss_import_sec_context(minor_status, 2461 input_token, 2462 context_handle) 2463 OM_uint32 *minor_status; 2464 gss_buffer_t input_token; 2465 gss_ctx_id_t *context_handle; 2466 { 2467 struct kgss_ctx *kctx; 2468 2469 if (*context_handle == GSS_C_NO_CONTEXT) { 2470 kctx = KGSS_ALLOC(); 2471 *context_handle = (gss_ctx_id_t)kctx; 2472 kctx->gssd_ctx = (OM_uint32) GSS_C_NO_CONTEXT; 2473 } else 2474 kctx = (struct kgss_ctx *)*context_handle; 2475 return (kgss_import_sec_context_wrapped(minor_status, 2476 input_token, &kctx->gssd_ctx, 2477 KCTX_TO_CTXV(context_handle))); 2478 } 2479 2480 #ifdef _KERNEL 2481 #include <sys/modctl.h> 2482 2483 static void *gss_clnt = NULL; 2484 2485 #ifdef DEBUG 2486 typedef struct { 2487 char *name; /* just put something here */ 2488 } gssd_devstate_t; 2489 2490 2491 static void *gssd_state; 2492 2493 static int gssd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2494 { 2495 /* cmn_err(CE_NOTE, "In gssd_attach"); */ 2496 switch (cmd) { 2497 case DDI_ATTACH: 2498 if (ddi_create_minor_node(dip, "gssd", S_IFCHR, 0, "gssd", 0) 2499 == DDI_FAILURE) { 2500 ddi_remove_minor_node(dip, NULL); 2501 return (DDI_FAILURE); 2502 } 2503 return (DDI_SUCCESS); 2504 2505 default: 2506 return (DDI_FAILURE); 2507 } 2508 } 2509 2510 static int gssd_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, 2511 void *arg, void **result) 2512 { 2513 dev_t dev; 2514 int error; 2515 2516 /* cmn_err(CE_NOTE, "In gssd_getinfo"); */ 2517 2518 switch (infocmd) { 2519 case DDI_INFO_DEVT2INSTANCE: 2520 dev = (dev_t)arg; 2521 *result = (void *) getminor(dev); 2522 error = DDI_SUCCESS; 2523 break; 2524 2525 case DDI_INFO_DEVT2DEVINFO: 2526 /* cmn_err(CE_NOTE, "getinfo wants devinfo"); */ 2527 default: 2528 error = DDI_FAILURE; 2529 break; 2530 } 2531 return (error); 2532 } 2533 2534 static int gssd_identify(dev_info_t *dip) 2535 { 2536 /* cmn_err(CE_NOTE, "in gssd_identify"); */ 2537 if (strcmp(ddi_get_name(dip), "gssd") == 0) 2538 return (DDI_IDENTIFIED); 2539 else 2540 return (DDI_NOT_IDENTIFIED); 2541 } 2542 2543 static int gssd_probe(dev_info_t *dip) 2544 { 2545 /* cmn_err(CE_NOTE, "In gssd_probe"); */ 2546 2547 return (DDI_PROBE_SUCCESS); 2548 } 2549 2550 static int gssd_open(dev_t *devp, int flag, int otyp, cred_t *credp) 2551 { 2552 /* cmn_err (CE_NOTE, "In gssd_open"); */ 2553 if (otyp != OTYP_CHR) 2554 return (EINVAL); 2555 2556 gss_clnt = getgssd_handle(); 2557 return (0); 2558 } 2559 2560 static int gssd_close(dev_t dev, int flag, int otyp, cred_t *credp) 2561 { 2562 /* cmn_err(CE_NOTE, "In gssd_close"); */ 2563 killgssd_handle(gss_clnt); 2564 return (0); 2565 } 2566 2567 static int gssd_write(dev_t dev, struct uio *uiop, cred_t *credp) 2568 { 2569 char buffer[1024]; 2570 int len; 2571 2572 /* cmn_err(CE_NOTE, "In gssd_write"); */ 2573 bzero(buffer, 1024); 2574 2575 uiomove(buffer, 1024, UIO_WRITE, uiop); 2576 len = strlen(buffer); 2577 2578 if (buffer[len-1] == '\n') 2579 buffer[--len] = '\0'; 2580 2581 cmn_err(CE_NOTE, "Got command: (%d) \"%s\"", len, buffer); 2582 do_gssdtest(buffer); 2583 return (0); 2584 } 2585 2586 static struct cb_ops gssd_cb_ops = { 2587 gssd_open, /* cb_open */ 2588 gssd_close, /* cb_close */ 2589 nodev, /* cb_strategy */ 2590 nodev, /* cb_print */ 2591 nodev, /* cb_dump */ 2592 nulldev, /* cb_read */ 2593 gssd_write, /* cb_write */ 2594 nodev, /* cb_ioctl */ 2595 nodev, /* cb_devmap */ 2596 nodev, /* cb_mmap */ 2597 nodev, /* cb_segmap */ 2598 nochpoll, /* cb_chpoll */ 2599 ddi_prop_op, /* cb_prop_op */ 2600 NULL, /* cb_stream */ 2601 (int)(D_NEW|D_MP) /* cb_flag */ 2602 }; 2603 2604 static struct dev_ops gssd_ops = { 2605 DEVO_REV, /* devo_rev */ 2606 0, /* devo_refcnt */ 2607 gssd_getinfo, /* devo_getinfo */ 2608 gssd_identify, /* devo_identify */ 2609 nulldev, /* devo_probe */ 2610 gssd_attach, /* devo_attach */ 2611 nulldev, /* devo_detach */ 2612 nodev, /* devo_reset */ 2613 &gssd_cb_ops, /* devo_cb_ops */ 2614 (struct bus_ops *)NULL /* devo_bus_ops */ 2615 }; 2616 2617 extern struct mod_ops mod_driverops; 2618 2619 static struct modldrv modlmisc = { 2620 &mod_driverops, 2621 "GSSD DRV Client Module", 2622 &gssd_ops 2623 2624 #else /* !DEBUG */ 2625 2626 static struct modlmisc modlmisc = { 2627 &mod_miscops, 2628 "GSSD Client Module" 2629 #endif /* DEBUG */ 2630 }; 2631 2632 static struct modlinkage modlinkage = { 2633 MODREV_1, 2634 (void *)&modlmisc, 2635 NULL 2636 }; 2637 2638 char _depends_on[] = "strmod/rpcmod misc/tlimod"; 2639 2640 _init(void) 2641 { 2642 int status; 2643 2644 if ((status = ddi_soft_state_init(&gssd_state, 2645 sizeof (gssd_devstate_t), 1)) != 0) 2646 return (status); 2647 2648 if ((status = mod_install((struct modlinkage *)&modlinkage)) != 0) 2649 ddi_soft_state_fini(&gssd_state); 2650 2651 cmn_err(CE_NOTE, "gssd: I'm in the kernel: %d.", status); 2652 return (status); 2653 } 2654 2655 _fini() 2656 { 2657 int status; 2658 2659 killgssd_handle(gss_clnt); 2660 cmn_err(CE_NOTE, "gssd: Handle destroyed.. leaving module."); 2661 2662 if ((status = mod_remove(&modlinkage)) != 0) 2663 return (status); 2664 2665 ddi_soft_state_fini(&gssd_state); 2666 return (status); 2667 } 2668 2669 _info(modinfop) 2670 struct modinfo *modinfop; 2671 { 2672 return (mod_info(&modlinkage, modinfop)); 2673 } 2674 2675 #endif 2676