1 /*- 2 * Copyright (c) 2005 Doug Rabson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29 #include <gssapi/gssapi.h> 30 #include <gssapi/gssapi_krb5.h> 31 32 /* RCSID("$Id: gss_krb5.c 21889 2007-08-09 07:43:24Z lha $"); */ 33 34 #include <krb5.h> 35 #include <roken.h> 36 37 OM_uint32 38 gss_krb5_copy_ccache(OM_uint32 *minor_status, 39 gss_cred_id_t cred, 40 krb5_ccache out) 41 { 42 gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; 43 krb5_context context; 44 krb5_error_code kret; 45 krb5_ccache id; 46 OM_uint32 ret; 47 char *str; 48 49 ret = gss_inquire_cred_by_oid(minor_status, 50 cred, 51 GSS_KRB5_COPY_CCACHE_X, 52 &data_set); 53 if (ret) 54 return ret; 55 56 if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) { 57 gss_release_buffer_set(minor_status, &data_set); 58 *minor_status = EINVAL; 59 return GSS_S_FAILURE; 60 } 61 62 kret = krb5_init_context(&context); 63 if (kret) { 64 *minor_status = kret; 65 gss_release_buffer_set(minor_status, &data_set); 66 return GSS_S_FAILURE; 67 } 68 69 kret = asprintf(&str, "%.*s", (int)data_set->elements[0].length, 70 (char *)data_set->elements[0].value); 71 gss_release_buffer_set(minor_status, &data_set); 72 if (kret == -1) { 73 *minor_status = ENOMEM; 74 return GSS_S_FAILURE; 75 } 76 77 kret = krb5_cc_resolve(context, str, &id); 78 free(str); 79 if (kret) { 80 *minor_status = kret; 81 return GSS_S_FAILURE; 82 } 83 84 kret = krb5_cc_copy_cache(context, id, out); 85 krb5_cc_close(context, id); 86 krb5_free_context(context); 87 if (kret) { 88 *minor_status = kret; 89 return GSS_S_FAILURE; 90 } 91 92 return ret; 93 } 94 95 OM_uint32 96 gss_krb5_import_cred(OM_uint32 *minor_status, 97 krb5_ccache id, 98 krb5_principal keytab_principal, 99 krb5_keytab keytab, 100 gss_cred_id_t *cred) 101 { 102 gss_buffer_desc buffer; 103 OM_uint32 major_status; 104 krb5_context context; 105 krb5_error_code ret; 106 krb5_storage *sp; 107 krb5_data data; 108 char *str; 109 110 *cred = GSS_C_NO_CREDENTIAL; 111 112 ret = krb5_init_context(&context); 113 if (ret) { 114 *minor_status = ret; 115 return GSS_S_FAILURE; 116 } 117 118 sp = krb5_storage_emem(); 119 if (sp == NULL) { 120 *minor_status = ENOMEM; 121 major_status = GSS_S_FAILURE; 122 goto out; 123 } 124 125 if (id) { 126 ret = krb5_cc_get_full_name(context, id, &str); 127 if (ret == 0) { 128 ret = krb5_store_string(sp, str); 129 free(str); 130 } 131 } else 132 ret = krb5_store_string(sp, ""); 133 if (ret) { 134 *minor_status = ret; 135 major_status = GSS_S_FAILURE; 136 goto out; 137 } 138 139 if (keytab_principal) { 140 ret = krb5_unparse_name(context, keytab_principal, &str); 141 if (ret == 0) { 142 ret = krb5_store_string(sp, str); 143 free(str); 144 } 145 } else 146 krb5_store_string(sp, ""); 147 if (ret) { 148 *minor_status = ret; 149 major_status = GSS_S_FAILURE; 150 goto out; 151 } 152 153 154 if (keytab) { 155 ret = krb5_kt_get_full_name(context, keytab, &str); 156 if (ret == 0) { 157 ret = krb5_store_string(sp, str); 158 free(str); 159 } 160 } else 161 krb5_store_string(sp, ""); 162 if (ret) { 163 *minor_status = ret; 164 major_status = GSS_S_FAILURE; 165 goto out; 166 } 167 168 ret = krb5_storage_to_data(sp, &data); 169 if (ret) { 170 *minor_status = ret; 171 major_status = GSS_S_FAILURE; 172 goto out; 173 } 174 175 buffer.value = data.data; 176 buffer.length = data.length; 177 178 major_status = gss_set_cred_option(minor_status, 179 cred, 180 GSS_KRB5_IMPORT_CRED_X, 181 &buffer); 182 krb5_data_free(&data); 183 out: 184 if (sp) 185 krb5_storage_free(sp); 186 krb5_free_context(context); 187 return major_status; 188 } 189 190 OM_uint32 191 gsskrb5_register_acceptor_identity(const char *identity) 192 { 193 gss_buffer_desc buffer; 194 OM_uint32 junk; 195 196 buffer.value = rk_UNCONST(identity); 197 buffer.length = strlen(identity); 198 199 gss_set_sec_context_option(&junk, NULL, 200 GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X, &buffer); 201 202 return (GSS_S_COMPLETE); 203 } 204 205 OM_uint32 206 gsskrb5_set_dns_canonicalize(int flag) 207 { 208 gss_buffer_desc buffer; 209 OM_uint32 junk; 210 char b = (flag != 0); 211 212 buffer.value = &b; 213 buffer.length = sizeof(b); 214 215 gss_set_sec_context_option(&junk, NULL, 216 GSS_KRB5_SET_DNS_CANONICALIZE_X, &buffer); 217 218 return (GSS_S_COMPLETE); 219 } 220 221 222 223 static krb5_error_code 224 set_key(krb5_keyblock *keyblock, gss_krb5_lucid_key_t *key) 225 { 226 key->type = keyblock->keytype; 227 key->length = keyblock->keyvalue.length; 228 key->data = malloc(key->length); 229 if (key->data == NULL && key->length != 0) 230 return ENOMEM; 231 memcpy(key->data, keyblock->keyvalue.data, key->length); 232 return 0; 233 } 234 235 static void 236 free_key(gss_krb5_lucid_key_t *key) 237 { 238 memset(key->data, 0, key->length); 239 free(key->data); 240 memset(key, 0, sizeof(*key)); 241 } 242 243 OM_uint32 244 gss_krb5_export_lucid_sec_context(OM_uint32 *minor_status, 245 gss_ctx_id_t *context_handle, 246 OM_uint32 version, 247 void **rctx) 248 { 249 krb5_context context = NULL; 250 krb5_error_code ret; 251 gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; 252 OM_uint32 major_status; 253 gss_krb5_lucid_context_v1_t *ctx = NULL; 254 krb5_storage *sp = NULL; 255 uint32_t num; 256 257 if (context_handle == NULL 258 || *context_handle == GSS_C_NO_CONTEXT 259 || version != 1) 260 { 261 ret = EINVAL; 262 return GSS_S_FAILURE; 263 } 264 265 major_status = 266 gss_inquire_sec_context_by_oid (minor_status, 267 *context_handle, 268 GSS_KRB5_EXPORT_LUCID_CONTEXT_V1_X, 269 &data_set); 270 if (major_status) 271 return major_status; 272 273 if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) { 274 gss_release_buffer_set(minor_status, &data_set); 275 *minor_status = EINVAL; 276 return GSS_S_FAILURE; 277 } 278 279 ret = krb5_init_context(&context); 280 if (ret) 281 goto out; 282 283 ctx = calloc(1, sizeof(*ctx)); 284 if (ctx == NULL) { 285 ret = ENOMEM; 286 goto out; 287 } 288 289 sp = krb5_storage_from_mem(data_set->elements[0].value, 290 data_set->elements[0].length); 291 if (sp == NULL) { 292 ret = ENOMEM; 293 goto out; 294 } 295 296 ret = krb5_ret_uint32(sp, &num); 297 if (ret) goto out; 298 if (num != 1) { 299 ret = EINVAL; 300 goto out; 301 } 302 ctx->version = 1; 303 /* initiator */ 304 ret = krb5_ret_uint32(sp, &ctx->initiate); 305 if (ret) goto out; 306 /* endtime */ 307 ret = krb5_ret_uint32(sp, &ctx->endtime); 308 if (ret) goto out; 309 /* send_seq */ 310 ret = krb5_ret_uint32(sp, &num); 311 if (ret) goto out; 312 ctx->send_seq = ((uint64_t)num) << 32; 313 ret = krb5_ret_uint32(sp, &num); 314 if (ret) goto out; 315 ctx->send_seq |= num; 316 /* recv_seq */ 317 ret = krb5_ret_uint32(sp, &num); 318 if (ret) goto out; 319 ctx->recv_seq = ((uint64_t)num) << 32; 320 ret = krb5_ret_uint32(sp, &num); 321 if (ret) goto out; 322 ctx->recv_seq |= num; 323 /* protocol */ 324 ret = krb5_ret_uint32(sp, &ctx->protocol); 325 if (ret) goto out; 326 if (ctx->protocol == 0) { 327 krb5_keyblock key; 328 329 /* sign_alg */ 330 ret = krb5_ret_uint32(sp, &ctx->rfc1964_kd.sign_alg); 331 if (ret) goto out; 332 /* seal_alg */ 333 ret = krb5_ret_uint32(sp, &ctx->rfc1964_kd.seal_alg); 334 if (ret) goto out; 335 /* ctx_key */ 336 ret = krb5_ret_keyblock(sp, &key); 337 if (ret) goto out; 338 ret = set_key(&key, &ctx->rfc1964_kd.ctx_key); 339 krb5_free_keyblock_contents(context, &key); 340 if (ret) goto out; 341 } else if (ctx->protocol == 1) { 342 krb5_keyblock key; 343 344 /* acceptor_subkey */ 345 ret = krb5_ret_uint32(sp, &ctx->cfx_kd.have_acceptor_subkey); 346 if (ret) goto out; 347 /* ctx_key */ 348 ret = krb5_ret_keyblock(sp, &key); 349 if (ret) goto out; 350 ret = set_key(&key, &ctx->cfx_kd.ctx_key); 351 krb5_free_keyblock_contents(context, &key); 352 if (ret) goto out; 353 /* acceptor_subkey */ 354 if (ctx->cfx_kd.have_acceptor_subkey) { 355 ret = krb5_ret_keyblock(sp, &key); 356 if (ret) goto out; 357 ret = set_key(&key, &ctx->cfx_kd.acceptor_subkey); 358 krb5_free_keyblock_contents(context, &key); 359 if (ret) goto out; 360 } 361 } else { 362 ret = EINVAL; 363 goto out; 364 } 365 366 *rctx = ctx; 367 368 out: 369 gss_release_buffer_set(minor_status, &data_set); 370 if (sp) 371 krb5_storage_free(sp); 372 if (context) 373 krb5_free_context(context); 374 375 if (ret) { 376 if (ctx) 377 gss_krb5_free_lucid_sec_context(NULL, ctx); 378 379 *minor_status = ret; 380 return GSS_S_FAILURE; 381 } 382 *minor_status = 0; 383 return GSS_S_COMPLETE; 384 } 385 386 OM_uint32 387 gss_krb5_free_lucid_sec_context(OM_uint32 *minor_status, void *c) 388 { 389 gss_krb5_lucid_context_v1_t *ctx = c; 390 391 if (ctx->version != 1) { 392 if (minor_status) 393 *minor_status = 0; 394 return GSS_S_FAILURE; 395 } 396 397 if (ctx->protocol == 0) { 398 free_key(&ctx->rfc1964_kd.ctx_key); 399 } else if (ctx->protocol == 1) { 400 free_key(&ctx->cfx_kd.ctx_key); 401 if (ctx->cfx_kd.have_acceptor_subkey) 402 free_key(&ctx->cfx_kd.acceptor_subkey); 403 } 404 free(ctx); 405 if (minor_status) 406 *minor_status = 0; 407 return GSS_S_COMPLETE; 408 } 409 410 /* 411 * 412 */ 413 414 OM_uint32 415 gss_krb5_set_allowable_enctypes(OM_uint32 *minor_status, 416 gss_cred_id_t cred, 417 OM_uint32 num_enctypes, 418 int32_t *enctypes) 419 { 420 krb5_error_code ret; 421 OM_uint32 maj_status; 422 gss_buffer_desc buffer; 423 krb5_storage *sp; 424 krb5_data data; 425 int i; 426 427 sp = krb5_storage_emem(); 428 if (sp == NULL) { 429 *minor_status = ENOMEM; 430 maj_status = GSS_S_FAILURE; 431 goto out; 432 } 433 434 for (i = 0; i < num_enctypes; i++) { 435 ret = krb5_store_int32(sp, enctypes[i]); 436 if (ret) { 437 *minor_status = ret; 438 maj_status = GSS_S_FAILURE; 439 goto out; 440 } 441 } 442 443 ret = krb5_storage_to_data(sp, &data); 444 if (ret) { 445 *minor_status = ret; 446 maj_status = GSS_S_FAILURE; 447 goto out; 448 } 449 450 buffer.value = data.data; 451 buffer.length = data.length; 452 453 maj_status = gss_set_cred_option(minor_status, 454 &cred, 455 GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X, 456 &buffer); 457 krb5_data_free(&data); 458 out: 459 if (sp) 460 krb5_storage_free(sp); 461 return maj_status; 462 } 463 464 /* 465 * 466 */ 467 468 OM_uint32 469 gsskrb5_set_send_to_kdc(struct gsskrb5_send_to_kdc *c) 470 { 471 gss_buffer_desc buffer; 472 OM_uint32 junk; 473 474 if (c) { 475 buffer.value = c; 476 buffer.length = sizeof(*c); 477 } else { 478 buffer.value = NULL; 479 buffer.length = 0; 480 } 481 482 gss_set_sec_context_option(&junk, NULL, 483 GSS_KRB5_SEND_TO_KDC_X, &buffer); 484 485 return (GSS_S_COMPLETE); 486 } 487 488 /* 489 * 490 */ 491 492 OM_uint32 493 gss_krb5_ccache_name(OM_uint32 *minor_status, 494 const char *name, 495 const char **out_name) 496 { 497 gss_buffer_desc buffer; 498 OM_uint32 junk; 499 500 if (out_name) 501 *out_name = NULL; 502 503 buffer.value = rk_UNCONST(name); 504 buffer.length = strlen(name); 505 506 gss_set_sec_context_option(&junk, NULL, 507 GSS_KRB5_CCACHE_NAME_X, &buffer); 508 509 return (GSS_S_COMPLETE); 510 } 511 512 513 /* 514 * 515 */ 516 517 OM_uint32 518 gsskrb5_extract_authtime_from_sec_context(OM_uint32 *minor_status, 519 gss_ctx_id_t context_handle, 520 time_t *authtime) 521 { 522 gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; 523 OM_uint32 maj_stat; 524 525 if (context_handle == GSS_C_NO_CONTEXT) { 526 *minor_status = EINVAL; 527 return GSS_S_FAILURE; 528 } 529 530 maj_stat = 531 gss_inquire_sec_context_by_oid (minor_status, 532 context_handle, 533 GSS_KRB5_GET_AUTHTIME_X, 534 &data_set); 535 if (maj_stat) 536 return maj_stat; 537 538 if (data_set == GSS_C_NO_BUFFER_SET) { 539 gss_release_buffer_set(minor_status, &data_set); 540 *minor_status = EINVAL; 541 return GSS_S_FAILURE; 542 } 543 544 if (data_set->count != 1) { 545 gss_release_buffer_set(minor_status, &data_set); 546 *minor_status = EINVAL; 547 return GSS_S_FAILURE; 548 } 549 550 if (data_set->elements[0].length != 4) { 551 gss_release_buffer_set(minor_status, &data_set); 552 *minor_status = EINVAL; 553 return GSS_S_FAILURE; 554 } 555 556 { 557 unsigned char *buf = data_set->elements[0].value; 558 *authtime = (buf[3] <<24) | (buf[2] << 16) | 559 (buf[1] << 8) | (buf[0] << 0); 560 } 561 562 gss_release_buffer_set(minor_status, &data_set); 563 564 *minor_status = 0; 565 return GSS_S_COMPLETE; 566 } 567 568 /* 569 * 570 */ 571 572 OM_uint32 573 gsskrb5_extract_authz_data_from_sec_context(OM_uint32 *minor_status, 574 gss_ctx_id_t context_handle, 575 int ad_type, 576 gss_buffer_t ad_data) 577 { 578 gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; 579 OM_uint32 maj_stat; 580 gss_OID_desc oid_flat; 581 heim_oid baseoid, oid; 582 size_t size; 583 584 if (context_handle == GSS_C_NO_CONTEXT) { 585 *minor_status = EINVAL; 586 return GSS_S_FAILURE; 587 } 588 589 /* All this to append an integer to an oid... */ 590 591 if (der_get_oid(GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X->elements, 592 GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X->length, 593 &baseoid, NULL) != 0) { 594 *minor_status = EINVAL; 595 return GSS_S_FAILURE; 596 } 597 598 oid.length = baseoid.length + 1; 599 oid.components = calloc(oid.length, sizeof(*oid.components)); 600 if (oid.components == NULL) { 601 der_free_oid(&baseoid); 602 603 *minor_status = ENOMEM; 604 return GSS_S_FAILURE; 605 } 606 607 memcpy(oid.components, baseoid.components, 608 baseoid.length * sizeof(*baseoid.components)); 609 610 der_free_oid(&baseoid); 611 612 oid.components[oid.length - 1] = ad_type; 613 614 oid_flat.length = der_length_oid(&oid); 615 oid_flat.elements = malloc(oid_flat.length); 616 if (oid_flat.elements == NULL) { 617 free(oid.components); 618 *minor_status = ENOMEM; 619 return GSS_S_FAILURE; 620 } 621 622 if (der_put_oid((unsigned char *)oid_flat.elements + oid_flat.length - 1, 623 oid_flat.length, &oid, &size) != 0) { 624 free(oid.components); 625 free(oid_flat.elements); 626 *minor_status = EINVAL; 627 return GSS_S_FAILURE; 628 } 629 if (oid_flat.length != size) 630 abort(); 631 632 free(oid.components); 633 634 /* FINALLY, we have the OID */ 635 636 maj_stat = gss_inquire_sec_context_by_oid (minor_status, 637 context_handle, 638 &oid_flat, 639 &data_set); 640 641 free(oid_flat.elements); 642 643 if (maj_stat) 644 return maj_stat; 645 646 if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) { 647 gss_release_buffer_set(minor_status, &data_set); 648 *minor_status = EINVAL; 649 return GSS_S_FAILURE; 650 } 651 652 ad_data->value = malloc(data_set->elements[0].length); 653 if (ad_data->value == NULL) { 654 gss_release_buffer_set(minor_status, &data_set); 655 *minor_status = ENOMEM; 656 return GSS_S_FAILURE; 657 } 658 659 ad_data->length = data_set->elements[0].length; 660 memcpy(ad_data->value, data_set->elements[0].value, ad_data->length); 661 gss_release_buffer_set(minor_status, &data_set); 662 663 *minor_status = 0; 664 return GSS_S_COMPLETE; 665 } 666 667 /* 668 * 669 */ 670 671 static OM_uint32 672 gsskrb5_extract_key(OM_uint32 *minor_status, 673 gss_ctx_id_t context_handle, 674 const gss_OID oid, 675 krb5_keyblock **keyblock) 676 { 677 krb5_error_code ret; 678 gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; 679 OM_uint32 major_status; 680 krb5_context context = NULL; 681 krb5_storage *sp = NULL; 682 683 if (context_handle == GSS_C_NO_CONTEXT) { 684 ret = EINVAL; 685 return GSS_S_FAILURE; 686 } 687 688 ret = krb5_init_context(&context); 689 if(ret) { 690 *minor_status = ret; 691 return GSS_S_FAILURE; 692 } 693 694 major_status = 695 gss_inquire_sec_context_by_oid (minor_status, 696 context_handle, 697 oid, 698 &data_set); 699 if (major_status) 700 return major_status; 701 702 if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) { 703 gss_release_buffer_set(minor_status, &data_set); 704 *minor_status = EINVAL; 705 return GSS_S_FAILURE; 706 } 707 708 sp = krb5_storage_from_mem(data_set->elements[0].value, 709 data_set->elements[0].length); 710 if (sp == NULL) { 711 ret = ENOMEM; 712 goto out; 713 } 714 715 *keyblock = calloc(1, sizeof(**keyblock)); 716 if (keyblock == NULL) { 717 ret = ENOMEM; 718 goto out; 719 } 720 721 ret = krb5_ret_keyblock(sp, *keyblock); 722 723 out: 724 gss_release_buffer_set(minor_status, &data_set); 725 if (sp) 726 krb5_storage_free(sp); 727 if (ret && keyblock) { 728 krb5_free_keyblock(context, *keyblock); 729 *keyblock = NULL; 730 } 731 if (context) 732 krb5_free_context(context); 733 734 *minor_status = ret; 735 if (ret) 736 return GSS_S_FAILURE; 737 738 return GSS_S_COMPLETE; 739 } 740 741 /* 742 * 743 */ 744 745 OM_uint32 746 gsskrb5_extract_service_keyblock(OM_uint32 *minor_status, 747 gss_ctx_id_t context_handle, 748 krb5_keyblock **keyblock) 749 { 750 return gsskrb5_extract_key(minor_status, 751 context_handle, 752 GSS_KRB5_GET_SERVICE_KEYBLOCK_X, 753 keyblock); 754 } 755 756 OM_uint32 757 gsskrb5_get_initiator_subkey(OM_uint32 *minor_status, 758 gss_ctx_id_t context_handle, 759 krb5_keyblock **keyblock) 760 { 761 return gsskrb5_extract_key(minor_status, 762 context_handle, 763 GSS_KRB5_GET_INITIATOR_SUBKEY_X, 764 keyblock); 765 } 766 767 OM_uint32 768 gsskrb5_get_subkey(OM_uint32 *minor_status, 769 gss_ctx_id_t context_handle, 770 krb5_keyblock **keyblock) 771 { 772 return gsskrb5_extract_key(minor_status, 773 context_handle, 774 GSS_KRB5_GET_SUBKEY_X, 775 keyblock); 776 } 777 778 OM_uint32 779 gsskrb5_set_default_realm(const char *realm) 780 { 781 gss_buffer_desc buffer; 782 OM_uint32 junk; 783 784 buffer.value = rk_UNCONST(realm); 785 buffer.length = strlen(realm); 786 787 gss_set_sec_context_option(&junk, NULL, 788 GSS_KRB5_SET_DEFAULT_REALM_X, &buffer); 789 790 return (GSS_S_COMPLETE); 791 } 792 793 OM_uint32 794 gss_krb5_get_tkt_flags(OM_uint32 *minor_status, 795 gss_ctx_id_t context_handle, 796 OM_uint32 *tkt_flags) 797 { 798 799 OM_uint32 major_status; 800 gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; 801 802 if (context_handle == GSS_C_NO_CONTEXT) { 803 *minor_status = EINVAL; 804 return GSS_S_FAILURE; 805 } 806 807 major_status = 808 gss_inquire_sec_context_by_oid (minor_status, 809 context_handle, 810 GSS_KRB5_GET_TKT_FLAGS_X, 811 &data_set); 812 if (major_status) 813 return major_status; 814 815 if (data_set == GSS_C_NO_BUFFER_SET || 816 data_set->count != 1 || 817 data_set->elements[0].length < 4) { 818 gss_release_buffer_set(minor_status, &data_set); 819 *minor_status = EINVAL; 820 return GSS_S_FAILURE; 821 } 822 823 { 824 const u_char *p = data_set->elements[0].value; 825 *tkt_flags = (p[0] << 0) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); 826 } 827 828 gss_release_buffer_set(minor_status, &data_set); 829 return GSS_S_COMPLETE; 830 } 831 832