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