get_in_tkt.c revision 72445
1280437Sandrew/* 2280437Sandrew * Copyright (c) 1997 - 2000 Kungliga Tekniska H�gskolan 3280704Sandrew * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#include "krb5_locl.h" 35 36RCSID("$Id: get_in_tkt.c,v 1.97 2000/08/18 06:47:54 assar Exp $"); 37 38krb5_error_code 39krb5_init_etype (krb5_context context, 40 unsigned *len, 41 int **val, 42 const krb5_enctype *etypes) 43{ 44 int i; 45 krb5_error_code ret; 46 krb5_enctype *tmp; 47 48 ret = 0; 49 if (etypes) 50 tmp = (krb5_enctype*)etypes; 51 else { 52 ret = krb5_get_default_in_tkt_etypes(context, 53 &tmp); 54 if (ret) 55 return ret; 56 } 57 58 for (i = 0; tmp[i]; ++i) 59 ; 60 *len = i; 61 *val = malloc(i * sizeof(int)); 62 if (i != 0 && *val == NULL) { 63 ret = ENOMEM; 64 goto cleanup; 65 } 66 memmove (*val, 67 tmp, 68 i * sizeof(*tmp)); 69cleanup: 70 if (etypes == NULL) 71 free (tmp); 72 return ret; 73} 74 75 76static krb5_error_code 77decrypt_tkt (krb5_context context, 78 krb5_keyblock *key, 79 krb5_key_usage usage, 80 krb5_const_pointer decrypt_arg, 81 krb5_kdc_rep *dec_rep) 82{ 83 krb5_error_code ret; 84 krb5_data data; 85 size_t size; 86 krb5_crypto crypto; 87 88 ret = krb5_crypto_init(context, key, 0, &crypto); 89 if (ret) 90 return ret; 91 92 ret = krb5_decrypt_EncryptedData (context, 93 crypto, 94 usage, 95 &dec_rep->kdc_rep.enc_part, 96 &data); 97 krb5_crypto_destroy(context, crypto); 98 99 if (ret) 100 return ret; 101 102 ret = krb5_decode_EncASRepPart(context, 103 data.data, 104 data.length, 105 &dec_rep->enc_part, 106 &size); 107 if (ret) 108 ret = krb5_decode_EncTGSRepPart(context, 109 data.data, 110 data.length, 111 &dec_rep->enc_part, 112 &size); 113 krb5_data_free (&data); 114 if (ret) 115 return ret; 116 return 0; 117} 118 119int 120_krb5_extract_ticket(krb5_context context, 121 krb5_kdc_rep *rep, 122 krb5_creds *creds, 123 krb5_keyblock *key, 124 krb5_const_pointer keyseed, 125 krb5_key_usage key_usage, 126 krb5_addresses *addrs, 127 unsigned nonce, 128 krb5_boolean allow_server_mismatch, 129 krb5_boolean ignore_cname, 130 krb5_decrypt_proc decrypt_proc, 131 krb5_const_pointer decryptarg) 132{ 133 krb5_error_code ret; 134 krb5_principal tmp_principal; 135 int tmp; 136 time_t tmp_time; 137 krb5_timestamp sec_now; 138 139 ret = principalname2krb5_principal (&tmp_principal, 140 rep->kdc_rep.cname, 141 rep->kdc_rep.crealm); 142 if (ret) 143 goto out; 144 145 /* compare client */ 146 147 if (!ignore_cname) { 148 tmp = krb5_principal_compare (context, tmp_principal, creds->client); 149 if (!tmp) { 150 krb5_free_principal (context, tmp_principal); 151 ret = KRB5KRB_AP_ERR_MODIFIED; 152 goto out; 153 } 154 } 155 156 krb5_free_principal (context, creds->client); 157 creds->client = tmp_principal; 158 159 /* extract ticket */ 160 { 161 unsigned char *buf; 162 size_t len; 163 len = length_Ticket(&rep->kdc_rep.ticket); 164 buf = malloc(len); 165 if(buf == NULL) { 166 ret = ENOMEM; 167 goto out; 168 } 169 encode_Ticket(buf + len - 1, len, &rep->kdc_rep.ticket, &len); 170 creds->ticket.data = buf; 171 creds->ticket.length = len; 172 creds->second_ticket.length = 0; 173 creds->second_ticket.data = NULL; 174 } 175 176 /* compare server */ 177 178 ret = principalname2krb5_principal (&tmp_principal, 179 rep->kdc_rep.ticket.sname, 180 rep->kdc_rep.ticket.realm); 181 if (ret) 182 goto out; 183 if(allow_server_mismatch){ 184 krb5_free_principal(context, creds->server); 185 creds->server = tmp_principal; 186 tmp_principal = NULL; 187 }else{ 188 tmp = krb5_principal_compare (context, tmp_principal, creds->server); 189 krb5_free_principal (context, tmp_principal); 190 if (!tmp) { 191 ret = KRB5KRB_AP_ERR_MODIFIED; 192 goto out; 193 } 194 } 195 196 /* decrypt */ 197 198 if (decrypt_proc == NULL) 199 decrypt_proc = decrypt_tkt; 200 201 ret = (*decrypt_proc)(context, key, key_usage, decryptarg, rep); 202 if (ret) 203 goto out; 204 205#if 0 206 /* XXX should this decode be here, or in the decrypt_proc? */ 207 ret = krb5_decode_keyblock(context, &rep->enc_part.key, 1); 208 if(ret) 209 goto out; 210#endif 211 212 /* compare nonces */ 213 214 if (nonce != rep->enc_part.nonce) { 215 ret = KRB5KRB_AP_ERR_MODIFIED; 216 goto out; 217 } 218 219 /* set kdc-offset */ 220 221 krb5_timeofday (context, &sec_now); 222 if (context->kdc_sec_offset == 0 223 && krb5_config_get_bool (context, NULL, 224 "libdefaults", 225 "kdc_timesync", 226 NULL)) { 227 context->kdc_sec_offset = rep->enc_part.authtime - sec_now; 228 krb5_timeofday (context, &sec_now); 229 } 230 231 /* check all times */ 232 233 if (rep->enc_part.starttime) { 234 tmp_time = *rep->enc_part.starttime; 235 } else 236 tmp_time = rep->enc_part.authtime; 237 238 if (creds->times.starttime == 0 239 && abs(tmp_time - sec_now) > context->max_skew) { 240 ret = KRB5KRB_AP_ERR_SKEW; 241 goto out; 242 } 243 244 if (creds->times.starttime != 0 245 && tmp_time != creds->times.starttime) { 246 ret = KRB5KRB_AP_ERR_MODIFIED; 247 goto out; 248 } 249 250 creds->times.starttime = tmp_time; 251 252 if (rep->enc_part.renew_till) { 253 tmp_time = *rep->enc_part.renew_till; 254 } else 255 tmp_time = 0; 256 257 if (creds->times.renew_till != 0 258 && tmp_time > creds->times.renew_till) { 259 ret = KRB5KRB_AP_ERR_MODIFIED; 260 goto out; 261 } 262 263 creds->times.renew_till = tmp_time; 264 265 creds->times.authtime = rep->enc_part.authtime; 266 267 if (creds->times.endtime != 0 268 && rep->enc_part.endtime > creds->times.endtime) { 269 ret = KRB5KRB_AP_ERR_MODIFIED; 270 goto out; 271 } 272 273 creds->times.endtime = rep->enc_part.endtime; 274 275 if(rep->enc_part.caddr) 276 krb5_copy_addresses (context, rep->enc_part.caddr, &creds->addresses); 277 else if(addrs) 278 krb5_copy_addresses (context, addrs, &creds->addresses); 279 else { 280 creds->addresses.len = 0; 281 creds->addresses.val = NULL; 282 } 283 creds->flags.b = rep->enc_part.flags; 284 285 creds->authdata.len = 0; 286 creds->authdata.val = NULL; 287 creds->session.keyvalue.length = 0; 288 creds->session.keyvalue.data = NULL; 289 creds->session.keytype = rep->enc_part.key.keytype; 290 ret = krb5_data_copy (&creds->session.keyvalue, 291 rep->enc_part.key.keyvalue.data, 292 rep->enc_part.key.keyvalue.length); 293 294out: 295 memset (rep->enc_part.key.keyvalue.data, 0, 296 rep->enc_part.key.keyvalue.length); 297 return ret; 298} 299 300 301static krb5_error_code 302make_pa_enc_timestamp(krb5_context context, PA_DATA *pa, 303 krb5_enctype etype, krb5_keyblock *key) 304{ 305 PA_ENC_TS_ENC p; 306 u_char buf[1024]; 307 size_t len; 308 EncryptedData encdata; 309 krb5_error_code ret; 310 int32_t sec, usec; 311 int usec2; 312 krb5_crypto crypto; 313 314 krb5_us_timeofday (context, &sec, &usec); 315 p.patimestamp = sec; 316 usec2 = usec; 317 p.pausec = &usec2; 318 319 ret = encode_PA_ENC_TS_ENC(buf + sizeof(buf) - 1, 320 sizeof(buf), 321 &p, 322 &len); 323 if (ret) 324 return ret; 325 326 ret = krb5_crypto_init(context, key, 0, &crypto); 327 if (ret) 328 return ret; 329 ret = krb5_encrypt_EncryptedData(context, 330 crypto, 331 KRB5_KU_PA_ENC_TIMESTAMP, 332 buf + sizeof(buf) - len, 333 len, 334 0, 335 &encdata); 336 krb5_crypto_destroy(context, crypto); 337 if (ret) 338 return ret; 339 340 ret = encode_EncryptedData(buf + sizeof(buf) - 1, 341 sizeof(buf), 342 &encdata, 343 &len); 344 free_EncryptedData(&encdata); 345 if (ret) 346 return ret; 347 pa->padata_type = KRB5_PADATA_ENC_TIMESTAMP; 348 pa->padata_value.length = 0; 349 krb5_data_copy(&pa->padata_value, 350 buf + sizeof(buf) - len, 351 len); 352 return 0; 353} 354 355static krb5_error_code 356add_padata(krb5_context context, 357 METHOD_DATA *md, 358 krb5_principal client, 359 krb5_key_proc key_proc, 360 krb5_const_pointer keyseed, 361 int *enctypes, 362 unsigned netypes, 363 krb5_salt *salt) 364{ 365 krb5_error_code ret; 366 PA_DATA *pa2; 367 krb5_salt salt2; 368 int *ep; 369 int i; 370 371 if(salt == NULL) { 372 /* default to standard salt */ 373 ret = krb5_get_pw_salt (context, client, &salt2); 374 salt = &salt2; 375 } 376 if (!enctypes) { 377 enctypes = (int *)context->etypes; /* XXX */ 378 netypes = 0; 379 for (ep = enctypes; *ep != ETYPE_NULL; ep++) 380 netypes++; 381 } 382 pa2 = realloc (md->val, (md->len + netypes) * sizeof(*md->val)); 383 if (pa2 == NULL) 384 return ENOMEM; 385 md->val = pa2; 386 387 for (i = 0; i < netypes; ++i) { 388 krb5_keyblock *key; 389 390 ret = (*key_proc)(context, enctypes[i], *salt, keyseed, &key); 391 if (ret) 392 continue; 393 ret = make_pa_enc_timestamp (context, &md->val[md->len], 394 enctypes[i], key); 395 krb5_free_keyblock (context, key); 396 if (ret) 397 return ret; 398 ++md->len; 399 } 400 if(salt == &salt2) 401 krb5_free_salt(context, salt2); 402 return 0; 403} 404 405static krb5_error_code 406init_as_req (krb5_context context, 407 krb5_kdc_flags opts, 408 krb5_creds *creds, 409 const krb5_addresses *addrs, 410 const krb5_enctype *etypes, 411 const krb5_preauthtype *ptypes, 412 const krb5_preauthdata *preauth, 413 krb5_key_proc key_proc, 414 krb5_const_pointer keyseed, 415 unsigned nonce, 416 AS_REQ *a) 417{ 418 krb5_error_code ret; 419 krb5_salt salt; 420 421 memset(a, 0, sizeof(*a)); 422 423 a->pvno = 5; 424 a->msg_type = krb_as_req; 425 a->req_body.kdc_options = opts.b; 426 a->req_body.cname = malloc(sizeof(*a->req_body.cname)); 427 if (a->req_body.cname == NULL) { 428 ret = ENOMEM; 429 goto fail; 430 } 431 a->req_body.sname = malloc(sizeof(*a->req_body.sname)); 432 if (a->req_body.sname == NULL) { 433 ret = ENOMEM; 434 goto fail; 435 } 436 ret = krb5_principal2principalname (a->req_body.cname, creds->client); 437 if (ret) 438 goto fail; 439 ret = krb5_principal2principalname (a->req_body.sname, creds->server); 440 if (ret) 441 goto fail; 442 ret = copy_Realm(&creds->client->realm, &a->req_body.realm); 443 if (ret) 444 goto fail; 445 446 if(creds->times.starttime) { 447 a->req_body.from = malloc(sizeof(*a->req_body.from)); 448 if (a->req_body.from == NULL) { 449 ret = ENOMEM; 450 goto fail; 451 } 452 *a->req_body.from = creds->times.starttime; 453 } 454 if(creds->times.endtime){ 455 ALLOC(a->req_body.till, 1); 456 *a->req_body.till = creds->times.endtime; 457 } 458 if(creds->times.renew_till){ 459 a->req_body.rtime = malloc(sizeof(*a->req_body.rtime)); 460 if (a->req_body.rtime == NULL) { 461 ret = ENOMEM; 462 goto fail; 463 } 464 *a->req_body.rtime = creds->times.renew_till; 465 } 466 a->req_body.nonce = nonce; 467 ret = krb5_init_etype (context, 468 &a->req_body.etype.len, 469 &a->req_body.etype.val, 470 etypes); 471 if (ret) 472 goto fail; 473 474 /* 475 * This means no addresses 476 */ 477 478 if (addrs && addrs->len == 0) { 479 a->req_body.addresses = NULL; 480 } else { 481 a->req_body.addresses = malloc(sizeof(*a->req_body.addresses)); 482 if (a->req_body.addresses == NULL) { 483 ret = ENOMEM; 484 goto fail; 485 } 486 487 if (addrs) 488 ret = krb5_copy_addresses(context, addrs, a->req_body.addresses); 489 else 490 ret = krb5_get_all_client_addrs (context, a->req_body.addresses); 491 if (ret) 492 return ret; 493 } 494 495 a->req_body.enc_authorization_data = NULL; 496 a->req_body.additional_tickets = NULL; 497 498 if(preauth != NULL) { 499 int i; 500 ALLOC(a->padata, 1); 501 if(a->padata == NULL) { 502 ret = ENOMEM; 503 goto fail; 504 } 505 for(i = 0; i < preauth->len; i++) { 506 if(preauth->val[i].type == KRB5_PADATA_ENC_TIMESTAMP){ 507 int j; 508 PA_DATA *tmp = realloc(a->padata->val, 509 (a->padata->len + 510 preauth->val[i].info.len) * 511 sizeof(*a->padata->val)); 512 if(tmp == NULL) { 513 ret = ENOMEM; 514 goto fail; 515 } 516 a->padata->val = tmp; 517 for(j = 0; j < preauth->val[i].info.len; j++) { 518 krb5_salt *sp = &salt; 519 if(preauth->val[i].info.val[j].salttype) 520 salt.salttype = *preauth->val[i].info.val[j].salttype; 521 else 522 salt.salttype = KRB5_PW_SALT; 523 if(preauth->val[i].info.val[j].salt) 524 salt.saltvalue = *preauth->val[i].info.val[j].salt; 525 else 526 if(salt.salttype == KRB5_PW_SALT) 527 sp = NULL; 528 else 529 krb5_data_zero(&salt.saltvalue); 530 add_padata(context, a->padata, creds->client, 531 key_proc, keyseed, 532 &preauth->val[i].info.val[j].etype, 1, 533 sp); 534 } 535 } 536 } 537 } else 538 /* not sure this is the way to use `ptypes' */ 539 if (ptypes == NULL || *ptypes == KRB5_PADATA_NONE) 540 a->padata = NULL; 541 else if (*ptypes == KRB5_PADATA_ENC_TIMESTAMP) { 542 ALLOC(a->padata, 1); 543 if (a->padata == NULL) { 544 ret = ENOMEM; 545 goto fail; 546 } 547 a->padata->len = 0; 548 a->padata->val = NULL; 549 550 /* make a v5 salted pa-data */ 551 add_padata(context, a->padata, creds->client, 552 key_proc, keyseed, a->req_body.etype.val, 553 a->req_body.etype.len, NULL); 554 555 /* make a v4 salted pa-data */ 556 salt.salttype = KRB5_PW_SALT; 557 krb5_data_zero(&salt.saltvalue); 558 add_padata(context, a->padata, creds->client, 559 key_proc, keyseed, a->req_body.etype.val, 560 a->req_body.etype.len, &salt); 561 } else { 562 ret = KRB5_PREAUTH_BAD_TYPE; 563 goto fail; 564 } 565 return 0; 566fail: 567 free_AS_REQ(a); 568 return ret; 569} 570 571static int 572set_ptypes(krb5_context context, 573 KRB_ERROR *error, 574 krb5_preauthtype **ptypes, 575 krb5_preauthdata **preauth) 576{ 577 static krb5_preauthdata preauth2; 578 static krb5_preauthtype ptypes2[] = { KRB5_PADATA_ENC_TIMESTAMP, KRB5_PADATA_NONE }; 579 580 if(error->e_data) { 581 METHOD_DATA md; 582 int i; 583 decode_METHOD_DATA(error->e_data->data, 584 error->e_data->length, 585 &md, 586 NULL); 587 for(i = 0; i < md.len; i++){ 588 switch(md.val[i].padata_type){ 589 case KRB5_PADATA_ENC_TIMESTAMP: 590 *ptypes = ptypes2; 591 break; 592 case KRB5_PADATA_ETYPE_INFO: 593 *preauth = &preauth2; 594 ALLOC_SEQ(*preauth, 1); 595 (*preauth)->val[0].type = KRB5_PADATA_ENC_TIMESTAMP; 596 krb5_decode_ETYPE_INFO(context, 597 md.val[i].padata_value.data, 598 md.val[i].padata_value.length, 599 &(*preauth)->val[0].info, 600 NULL); 601 break; 602 default: 603 break; 604 } 605 } 606 free_METHOD_DATA(&md); 607 } else { 608 *ptypes = ptypes2; 609 } 610 return(1); 611} 612 613krb5_error_code 614krb5_get_in_cred(krb5_context context, 615 krb5_flags options, 616 const krb5_addresses *addrs, 617 const krb5_enctype *etypes, 618 const krb5_preauthtype *ptypes, 619 const krb5_preauthdata *preauth, 620 krb5_key_proc key_proc, 621 krb5_const_pointer keyseed, 622 krb5_decrypt_proc decrypt_proc, 623 krb5_const_pointer decryptarg, 624 krb5_creds *creds, 625 krb5_kdc_rep *ret_as_reply) 626{ 627 krb5_error_code ret; 628 AS_REQ a; 629 krb5_kdc_rep rep; 630 krb5_data req, resp; 631 char buf[BUFSIZ]; 632 krb5_salt salt; 633 krb5_keyblock *key; 634 size_t size; 635 krb5_kdc_flags opts; 636 PA_DATA *pa; 637 krb5_enctype etype; 638 krb5_preauthdata *my_preauth = NULL; 639 unsigned nonce; 640 int done; 641 642 opts.i = options; 643 644 krb5_generate_random_block (&nonce, sizeof(nonce)); 645 nonce &= 0xffffffff; 646 647 do { 648 done = 1; 649 ret = init_as_req (context, 650 opts, 651 creds, 652 addrs, 653 etypes, 654 ptypes, 655 preauth, 656 key_proc, 657 keyseed, 658 nonce, 659 &a); 660 if (my_preauth) { 661 free_ETYPE_INFO(&my_preauth->val[0].info); 662 free (my_preauth->val); 663 } 664 if (ret) 665 return ret; 666 667 ret = encode_AS_REQ ((unsigned char*)buf + sizeof(buf) - 1, 668 sizeof(buf), 669 &a, 670 &req.length); 671 free_AS_REQ(&a); 672 if (ret) 673 return ret; 674 675 req.data = buf + sizeof(buf) - req.length; 676 677 ret = krb5_sendto_kdc (context, &req, &creds->client->realm, &resp); 678 if (ret) 679 return ret; 680 681 memset (&rep, 0, sizeof(rep)); 682 ret = decode_AS_REP(resp.data, resp.length, &rep.kdc_rep, &size); 683 if(ret) { 684 /* let's try to parse it as a KRB-ERROR */ 685 KRB_ERROR error; 686 int ret2; 687 688 ret2 = krb5_rd_error(context, &resp, &error); 689 if(ret2 && resp.data && ((char*)resp.data)[0] == 4) 690 ret = KRB5KRB_AP_ERR_V4_REPLY; 691 krb5_data_free(&resp); 692 if (ret2 == 0) { 693 ret = error.error_code; 694 /* if no preauth was set and KDC requires it, give it 695 one more try */ 696 if (!ptypes && !preauth 697 && ret == KRB5KDC_ERR_PREAUTH_REQUIRED 698#if 0 699 || ret == KRB5KDC_ERR_BADOPTION 700#endif 701 && set_ptypes(context, &error, &ptypes, &my_preauth)) { 702 done = 0; 703 preauth = my_preauth; 704 free_KRB_ERROR(&error); 705 continue; 706 } 707 if(ret_as_reply) 708 ret_as_reply->error = error; 709 else 710 free_KRB_ERROR (&error); 711 return ret; 712 } 713 return ret; 714 } 715 krb5_data_free(&resp); 716 } while(!done); 717 718 pa = NULL; 719 etype = rep.kdc_rep.enc_part.etype; 720 if(rep.kdc_rep.padata){ 721 int index = 0; 722 pa = krb5_find_padata(rep.kdc_rep.padata->val, rep.kdc_rep.padata->len, 723 KRB5_PADATA_PW_SALT, &index); 724 if(pa == NULL) { 725 index = 0; 726 pa = krb5_find_padata(rep.kdc_rep.padata->val, 727 rep.kdc_rep.padata->len, 728 KRB5_PADATA_AFS3_SALT, &index); 729 } 730 } 731 if(pa) { 732 salt.salttype = pa->padata_type; 733 salt.saltvalue = pa->padata_value; 734 735 ret = (*key_proc)(context, etype, salt, keyseed, &key); 736 } else { 737 /* make a v5 salted pa-data */ 738 ret = krb5_get_pw_salt (context, creds->client, &salt); 739 740 if (ret) 741 goto out; 742 ret = (*key_proc)(context, etype, salt, keyseed, &key); 743 krb5_free_salt(context, salt); 744 } 745 if (ret) 746 goto out; 747 748 ret = _krb5_extract_ticket(context, 749 &rep, 750 creds, 751 key, 752 keyseed, 753 KRB5_KU_AS_REP_ENC_PART, 754 NULL, 755 nonce, 756 FALSE, 757 opts.b.request_anonymous, 758 decrypt_proc, 759 decryptarg); 760 memset (key->keyvalue.data, 0, key->keyvalue.length); 761 krb5_free_keyblock_contents (context, key); 762 free (key); 763 764out: 765 if (ret == 0 && ret_as_reply) 766 *ret_as_reply = rep; 767 else 768 krb5_free_kdc_rep (context, &rep); 769 return ret; 770} 771 772krb5_error_code 773krb5_get_in_tkt(krb5_context context, 774 krb5_flags options, 775 const krb5_addresses *addrs, 776 const krb5_enctype *etypes, 777 const krb5_preauthtype *ptypes, 778 krb5_key_proc key_proc, 779 krb5_const_pointer keyseed, 780 krb5_decrypt_proc decrypt_proc, 781 krb5_const_pointer decryptarg, 782 krb5_creds *creds, 783 krb5_ccache ccache, 784 krb5_kdc_rep *ret_as_reply) 785{ 786 krb5_error_code ret; 787 krb5_kdc_flags opts; 788 opts.i = 0; 789 opts.b = int2KDCOptions(options); 790 791 ret = krb5_get_in_cred (context, 792 opts.i, 793 addrs, 794 etypes, 795 ptypes, 796 NULL, 797 key_proc, 798 keyseed, 799 decrypt_proc, 800 decryptarg, 801 creds, 802 ret_as_reply); 803 if(ret) 804 return ret; 805 ret = krb5_cc_store_cred (context, ccache, creds); 806 krb5_free_creds_contents (context, creds); 807 return ret; 808} 809