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