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