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