1/* 2 * Copyright (c) 1997 - 2001 Kungliga Tekniska H��gskolan 3 * (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 36krb5_error_code KRB5_LIB_FUNCTION 37krb5_free_ticket(krb5_context context, 38 krb5_ticket *ticket) 39{ 40 free_EncTicketPart(&ticket->ticket); 41 krb5_free_principal(context, ticket->client); 42 krb5_free_principal(context, ticket->server); 43 free(ticket); 44 return 0; 45} 46 47krb5_error_code KRB5_LIB_FUNCTION 48krb5_copy_ticket(krb5_context context, 49 const krb5_ticket *from, 50 krb5_ticket **to) 51{ 52 krb5_error_code ret; 53 krb5_ticket *tmp; 54 55 *to = NULL; 56 tmp = malloc(sizeof(*tmp)); 57 if(tmp == NULL) { 58 krb5_set_error_message(context, ENOMEM, 59 N_("malloc: out of memory", "")); 60 return ENOMEM; 61 } 62 if((ret = copy_EncTicketPart(&from->ticket, &tmp->ticket))){ 63 free(tmp); 64 return ret; 65 } 66 ret = krb5_copy_principal(context, from->client, &tmp->client); 67 if(ret){ 68 free_EncTicketPart(&tmp->ticket); 69 free(tmp); 70 return ret; 71 } 72 ret = krb5_copy_principal(context, from->server, &tmp->server); 73 if(ret){ 74 krb5_free_principal(context, tmp->client); 75 free_EncTicketPart(&tmp->ticket); 76 free(tmp); 77 return ret; 78 } 79 *to = tmp; 80 return 0; 81} 82 83krb5_error_code KRB5_LIB_FUNCTION 84krb5_ticket_get_client(krb5_context context, 85 const krb5_ticket *ticket, 86 krb5_principal *client) 87{ 88 return krb5_copy_principal(context, ticket->client, client); 89} 90 91krb5_error_code KRB5_LIB_FUNCTION 92krb5_ticket_get_server(krb5_context context, 93 const krb5_ticket *ticket, 94 krb5_principal *server) 95{ 96 return krb5_copy_principal(context, ticket->server, server); 97} 98 99time_t KRB5_LIB_FUNCTION 100krb5_ticket_get_endtime(krb5_context context, 101 const krb5_ticket *ticket) 102{ 103 return ticket->ticket.endtime; 104} 105 106/** 107 * Get the flags from the Kerberos ticket 108 * 109 * @param context Kerberos context 110 * @param ticket Kerberos ticket 111 * 112 * @return ticket flags 113 * 114 * @ingroup krb5_ticket 115 */ 116unsigned long 117krb5_ticket_get_flags(krb5_context context, 118 const krb5_ticket *ticket) 119{ 120 return TicketFlags2int(ticket->ticket.flags); 121} 122 123static int 124find_type_in_ad(krb5_context context, 125 int type, 126 krb5_data *data, 127 krb5_boolean *found, 128 krb5_boolean failp, 129 krb5_keyblock *sessionkey, 130 const AuthorizationData *ad, 131 int level) 132{ 133 krb5_error_code ret = 0; 134 int i; 135 136 if (level > 9) { 137 ret = ENOENT; /* XXX */ 138 krb5_set_error_message(context, ret, 139 N_("Authorization data nested deeper " 140 "then %d levels, stop searching", ""), 141 level); 142 goto out; 143 } 144 145 /* 146 * Only copy out the element the first time we get to it, we need 147 * to run over the whole authorization data fields to check if 148 * there are any container clases we need to care about. 149 */ 150 for (i = 0; i < ad->len; i++) { 151 if (!*found && ad->val[i].ad_type == type) { 152 ret = der_copy_octet_string(&ad->val[i].ad_data, data); 153 if (ret) { 154 krb5_set_error_message(context, ret, 155 N_("malloc: out of memory", "")); 156 goto out; 157 } 158 *found = TRUE; 159 continue; 160 } 161 switch (ad->val[i].ad_type) { 162 case KRB5_AUTHDATA_IF_RELEVANT: { 163 AuthorizationData child; 164 ret = decode_AuthorizationData(ad->val[i].ad_data.data, 165 ad->val[i].ad_data.length, 166 &child, 167 NULL); 168 if (ret) { 169 krb5_set_error_message(context, ret, 170 N_("Failed to decode " 171 "IF_RELEVANT with %d", ""), 172 (int)ret); 173 goto out; 174 } 175 ret = find_type_in_ad(context, type, data, found, FALSE, 176 sessionkey, &child, level + 1); 177 free_AuthorizationData(&child); 178 if (ret) 179 goto out; 180 break; 181 } 182#if 0 /* XXX test */ 183 case KRB5_AUTHDATA_KDC_ISSUED: { 184 AD_KDCIssued child; 185 186 ret = decode_AD_KDCIssued(ad->val[i].ad_data.data, 187 ad->val[i].ad_data.length, 188 &child, 189 NULL); 190 if (ret) { 191 krb5_set_error_message(context, ret, 192 N_("Failed to decode " 193 "AD_KDCIssued with %d", ""), 194 ret); 195 goto out; 196 } 197 if (failp) { 198 krb5_boolean valid; 199 krb5_data buf; 200 size_t len; 201 202 ASN1_MALLOC_ENCODE(AuthorizationData, buf.data, buf.length, 203 &child.elements, &len, ret); 204 if (ret) { 205 free_AD_KDCIssued(&child); 206 krb5_clear_error_message(context); 207 goto out; 208 } 209 if(buf.length != len) 210 krb5_abortx(context, "internal error in ASN.1 encoder"); 211 212 ret = krb5_c_verify_checksum(context, sessionkey, 19, &buf, 213 &child.ad_checksum, &valid); 214 krb5_data_free(&buf); 215 if (ret) { 216 free_AD_KDCIssued(&child); 217 goto out; 218 } 219 if (!valid) { 220 krb5_clear_error_message(context); 221 ret = ENOENT; 222 free_AD_KDCIssued(&child); 223 goto out; 224 } 225 } 226 ret = find_type_in_ad(context, type, data, found, failp, sessionkey, 227 &child.elements, level + 1); 228 free_AD_KDCIssued(&child); 229 if (ret) 230 goto out; 231 break; 232 } 233#endif 234 case KRB5_AUTHDATA_AND_OR: 235 if (!failp) 236 break; 237 ret = ENOENT; /* XXX */ 238 krb5_set_error_message(context, ret, 239 N_("Authorization data contains " 240 "AND-OR element that is unknown to the " 241 "application", "")); 242 goto out; 243 default: 244 if (!failp) 245 break; 246 ret = ENOENT; /* XXX */ 247 krb5_set_error_message(context, ret, 248 N_("Authorization data contains " 249 "unknown type (%d) ", ""), 250 ad->val[i].ad_type); 251 goto out; 252 } 253 } 254out: 255 if (ret) { 256 if (*found) { 257 krb5_data_free(data); 258 *found = 0; 259 } 260 } 261 return ret; 262} 263 264/* 265 * Extract the authorization data type of `type' from the 266 * 'ticket'. Store the field in `data'. This function is to use for 267 * kerberos applications. 268 */ 269 270krb5_error_code KRB5_LIB_FUNCTION 271krb5_ticket_get_authorization_data_type(krb5_context context, 272 krb5_ticket *ticket, 273 int type, 274 krb5_data *data) 275{ 276 AuthorizationData *ad; 277 krb5_error_code ret; 278 krb5_boolean found = FALSE; 279 280 krb5_data_zero(data); 281 282 ad = ticket->ticket.authorization_data; 283 if (ticket->ticket.authorization_data == NULL) { 284 krb5_set_error_message(context, ENOENT, 285 N_("Ticket have not authorization data", "")); 286 return ENOENT; /* XXX */ 287 } 288 289 ret = find_type_in_ad(context, type, data, &found, TRUE, 290 &ticket->ticket.key, ad, 0); 291 if (ret) 292 return ret; 293 if (!found) { 294 krb5_set_error_message(context, ENOENT, 295 N_("Ticket have not " 296 "authorization data of type %d", ""), 297 type); 298 return ENOENT; /* XXX */ 299 } 300 return 0; 301} 302 303static krb5_error_code 304check_server_referral(krb5_context context, 305 krb5_kdc_rep *rep, 306 unsigned flags, 307 krb5_const_principal requested, 308 krb5_const_principal returned, 309 krb5_keyblock * key) 310{ 311 krb5_error_code ret; 312 PA_ServerReferralData ref; 313 krb5_crypto session; 314 EncryptedData ed; 315 size_t len; 316 krb5_data data; 317 PA_DATA *pa; 318 int i = 0, cmp; 319 320 if (rep->kdc_rep.padata == NULL) 321 goto noreferral; 322 323 pa = krb5_find_padata(rep->kdc_rep.padata->val, 324 rep->kdc_rep.padata->len, 325 KRB5_PADATA_SERVER_REFERRAL, &i); 326 if (pa == NULL) 327 goto noreferral; 328 329 memset(&ed, 0, sizeof(ed)); 330 memset(&ref, 0, sizeof(ref)); 331 332 ret = decode_EncryptedData(pa->padata_value.data, 333 pa->padata_value.length, 334 &ed, &len); 335 if (ret) 336 return ret; 337 if (len != pa->padata_value.length) { 338 free_EncryptedData(&ed); 339 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, 340 N_("Referral EncryptedData wrong for realm %s", 341 "realm"), requested->realm); 342 return KRB5KRB_AP_ERR_MODIFIED; 343 } 344 345 ret = krb5_crypto_init(context, key, 0, &session); 346 if (ret) { 347 free_EncryptedData(&ed); 348 return ret; 349 } 350 351 ret = krb5_decrypt_EncryptedData(context, session, 352 KRB5_KU_PA_SERVER_REFERRAL, 353 &ed, &data); 354 free_EncryptedData(&ed); 355 krb5_crypto_destroy(context, session); 356 if (ret) 357 return ret; 358 359 ret = decode_PA_ServerReferralData(data.data, data.length, &ref, &len); 360 if (ret) { 361 krb5_data_free(&data); 362 return ret; 363 } 364 krb5_data_free(&data); 365 366 if (strcmp(requested->realm, returned->realm) != 0) { 367 free_PA_ServerReferralData(&ref); 368 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, 369 N_("server ref realm mismatch, " 370 "requested realm %s got back %s", ""), 371 requested->realm, returned->realm); 372 return KRB5KRB_AP_ERR_MODIFIED; 373 } 374 375 if (returned->name.name_string.len == 2 && 376 strcmp(returned->name.name_string.val[0], KRB5_TGS_NAME) == 0) 377 { 378 const char *realm = returned->name.name_string.val[1]; 379 380 if (ref.referred_realm == NULL 381 || strcmp(*ref.referred_realm, realm) != 0) 382 { 383 free_PA_ServerReferralData(&ref); 384 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, 385 N_("tgt returned with wrong ref", "")); 386 return KRB5KRB_AP_ERR_MODIFIED; 387 } 388 } else if (krb5_principal_compare(context, returned, requested) == 0) { 389 free_PA_ServerReferralData(&ref); 390 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, 391 N_("req princ no same as returned", "")); 392 return KRB5KRB_AP_ERR_MODIFIED; 393 } 394 395 if (ref.requested_principal_name) { 396 cmp = _krb5_principal_compare_PrincipalName(context, 397 requested, 398 ref.requested_principal_name); 399 if (!cmp) { 400 free_PA_ServerReferralData(&ref); 401 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, 402 N_("referred principal not same " 403 "as requested", "")); 404 return KRB5KRB_AP_ERR_MODIFIED; 405 } 406 } else if (flags & EXTRACT_TICKET_AS_REQ) { 407 free_PA_ServerReferralData(&ref); 408 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, 409 N_("Requested principal missing on AS-REQ", "")); 410 return KRB5KRB_AP_ERR_MODIFIED; 411 } 412 413 free_PA_ServerReferralData(&ref); 414 415 return ret; 416noreferral: 417 if (krb5_principal_compare(context, requested, returned) == FALSE) { 418 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, 419 N_("Not same server principal returned " 420 "as requested", "")); 421 return KRB5KRB_AP_ERR_MODIFIED; 422 } 423 return 0; 424} 425 426 427/* 428 * Verify referral data 429 */ 430 431 432static krb5_error_code 433check_client_referral(krb5_context context, 434 krb5_kdc_rep *rep, 435 krb5_const_principal requested, 436 krb5_const_principal mapped, 437 krb5_keyblock const * key) 438{ 439 krb5_error_code ret; 440 PA_ClientCanonicalized canon; 441 krb5_crypto crypto; 442 krb5_data data; 443 PA_DATA *pa; 444 size_t len; 445 int i = 0; 446 447 if (rep->kdc_rep.padata == NULL) 448 goto noreferral; 449 450 pa = krb5_find_padata(rep->kdc_rep.padata->val, 451 rep->kdc_rep.padata->len, 452 KRB5_PADATA_CLIENT_CANONICALIZED, &i); 453 if (pa == NULL) 454 goto noreferral; 455 456 ret = decode_PA_ClientCanonicalized(pa->padata_value.data, 457 pa->padata_value.length, 458 &canon, &len); 459 if (ret) { 460 krb5_set_error_message(context, ret, 461 N_("Failed to decode ClientCanonicalized " 462 "from realm %s", ""), requested->realm); 463 return ret; 464 } 465 466 ASN1_MALLOC_ENCODE(PA_ClientCanonicalizedNames, data.data, data.length, 467 &canon.names, &len, ret); 468 if (ret) { 469 free_PA_ClientCanonicalized(&canon); 470 return ret; 471 } 472 if (data.length != len) 473 krb5_abortx(context, "internal asn.1 error"); 474 475 ret = krb5_crypto_init(context, key, 0, &crypto); 476 if (ret) { 477 free(data.data); 478 free_PA_ClientCanonicalized(&canon); 479 return ret; 480 } 481 482 ret = krb5_verify_checksum(context, crypto, KRB5_KU_CANONICALIZED_NAMES, 483 data.data, data.length, 484 &canon.canon_checksum); 485 krb5_crypto_destroy(context, crypto); 486 free(data.data); 487 if (ret) { 488 krb5_set_error_message(context, ret, 489 N_("Failed to verify client canonicalized " 490 "data from realm %s", ""), 491 requested->realm); 492 free_PA_ClientCanonicalized(&canon); 493 return ret; 494 } 495 496 if (!_krb5_principal_compare_PrincipalName(context, 497 requested, 498 &canon.names.requested_name)) 499 { 500 free_PA_ClientCanonicalized(&canon); 501 krb5_set_error_message(context, KRB5_PRINC_NOMATCH, 502 N_("Requested name doesn't match" 503 " in client referral", "")); 504 return KRB5_PRINC_NOMATCH; 505 } 506 if (!_krb5_principal_compare_PrincipalName(context, 507 mapped, 508 &canon.names.mapped_name)) 509 { 510 free_PA_ClientCanonicalized(&canon); 511 krb5_set_error_message(context, KRB5_PRINC_NOMATCH, 512 N_("Mapped name doesn't match" 513 " in client referral", "")); 514 return KRB5_PRINC_NOMATCH; 515 } 516 517 return 0; 518 519noreferral: 520 if (krb5_principal_compare(context, requested, mapped) == FALSE) { 521 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, 522 N_("Not same client principal returned " 523 "as requested", "")); 524 return KRB5KRB_AP_ERR_MODIFIED; 525 } 526 return 0; 527} 528 529 530static krb5_error_code 531decrypt_tkt (krb5_context context, 532 krb5_keyblock *key, 533 krb5_key_usage usage, 534 krb5_const_pointer decrypt_arg, 535 krb5_kdc_rep *dec_rep) 536{ 537 krb5_error_code ret; 538 krb5_data data; 539 size_t size; 540 krb5_crypto crypto; 541 542 ret = krb5_crypto_init(context, key, 0, &crypto); 543 if (ret) 544 return ret; 545 546 ret = krb5_decrypt_EncryptedData (context, 547 crypto, 548 usage, 549 &dec_rep->kdc_rep.enc_part, 550 &data); 551 krb5_crypto_destroy(context, crypto); 552 553 if (ret) 554 return ret; 555 556 ret = decode_EncASRepPart(data.data, 557 data.length, 558 &dec_rep->enc_part, 559 &size); 560 if (ret) 561 ret = decode_EncTGSRepPart(data.data, 562 data.length, 563 &dec_rep->enc_part, 564 &size); 565 krb5_data_free (&data); 566 if (ret) { 567 krb5_set_error_message(context, ret, 568 N_("Failed to decode encpart in ticket", "")); 569 return ret; 570 } 571 return 0; 572} 573 574int 575_krb5_extract_ticket(krb5_context context, 576 krb5_kdc_rep *rep, 577 krb5_creds *creds, 578 krb5_keyblock *key, 579 krb5_const_pointer keyseed, 580 krb5_key_usage key_usage, 581 krb5_addresses *addrs, 582 unsigned nonce, 583 unsigned flags, 584 krb5_decrypt_proc decrypt_proc, 585 krb5_const_pointer decryptarg) 586{ 587 krb5_error_code ret; 588 krb5_principal tmp_principal; 589 size_t len; 590 time_t tmp_time; 591 krb5_timestamp sec_now; 592 593 /* decrypt */ 594 595 if (decrypt_proc == NULL) 596 decrypt_proc = decrypt_tkt; 597 598 ret = (*decrypt_proc)(context, key, key_usage, decryptarg, rep); 599 if (ret) 600 goto out; 601 602 /* save session key */ 603 604 creds->session.keyvalue.length = 0; 605 creds->session.keyvalue.data = NULL; 606 creds->session.keytype = rep->enc_part.key.keytype; 607 ret = krb5_data_copy (&creds->session.keyvalue, 608 rep->enc_part.key.keyvalue.data, 609 rep->enc_part.key.keyvalue.length); 610 if (ret) { 611 krb5_clear_error_message(context); 612 goto out; 613 } 614 615 /* 616 * HACK: 617 * this is really a ugly hack, to support using the Netbios Domain Name 618 * as realm against windows KDC's, they always return the full realm 619 * based on the DNS Name. 620 */ 621 flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH; 622 flags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH; 623 624 /* compare client and save */ 625 ret = _krb5_principalname2krb5_principal (context, 626 &tmp_principal, 627 rep->kdc_rep.cname, 628 rep->kdc_rep.crealm); 629 if (ret) 630 goto out; 631 632 /* check client referral and save principal */ 633 /* anonymous here ? */ 634 if((flags & EXTRACT_TICKET_ALLOW_CNAME_MISMATCH) == 0) { 635 ret = check_client_referral(context, rep, 636 creds->client, 637 tmp_principal, 638 &creds->session); 639 if (ret) { 640 krb5_free_principal (context, tmp_principal); 641 goto out; 642 } 643 } 644 krb5_free_principal (context, creds->client); 645 creds->client = tmp_principal; 646 647 /* check server referral and save principal */ 648 ret = _krb5_principalname2krb5_principal (context, 649 &tmp_principal, 650 rep->kdc_rep.ticket.sname, 651 rep->kdc_rep.ticket.realm); 652 if (ret) 653 goto out; 654 if((flags & EXTRACT_TICKET_ALLOW_SERVER_MISMATCH) == 0){ 655 ret = check_server_referral(context, 656 rep, 657 flags, 658 creds->server, 659 tmp_principal, 660 &creds->session); 661 if (ret) { 662 krb5_free_principal (context, tmp_principal); 663 goto out; 664 } 665 } 666 krb5_free_principal(context, creds->server); 667 creds->server = tmp_principal; 668 669 /* verify names */ 670 if(flags & EXTRACT_TICKET_MATCH_REALM){ 671 const char *srealm = krb5_principal_get_realm(context, creds->server); 672 const char *crealm = krb5_principal_get_realm(context, creds->client); 673 674 if (strcmp(rep->enc_part.srealm, srealm) != 0 || 675 strcmp(rep->enc_part.srealm, crealm) != 0) 676 { 677 ret = KRB5KRB_AP_ERR_MODIFIED; 678 krb5_clear_error_message(context); 679 goto out; 680 } 681 } 682 683 /* compare nonces */ 684 685 if (nonce != rep->enc_part.nonce) { 686 ret = KRB5KRB_AP_ERR_MODIFIED; 687 krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); 688 goto out; 689 } 690 691 /* set kdc-offset */ 692 693 krb5_timeofday (context, &sec_now); 694 if (rep->enc_part.flags.initial 695 && context->kdc_sec_offset == 0 696 && krb5_config_get_bool (context, NULL, 697 "libdefaults", 698 "kdc_timesync", 699 NULL)) { 700 context->kdc_sec_offset = rep->enc_part.authtime - sec_now; 701 krb5_timeofday (context, &sec_now); 702 } 703 704 /* check all times */ 705 706 if (rep->enc_part.starttime) { 707 tmp_time = *rep->enc_part.starttime; 708 } else 709 tmp_time = rep->enc_part.authtime; 710 711 if (creds->times.starttime == 0 712 && abs(tmp_time - sec_now) > context->max_skew) { 713 ret = KRB5KRB_AP_ERR_SKEW; 714 krb5_set_error_message (context, ret, 715 N_("time skew (%d) larger than max (%d)", ""), 716 abs(tmp_time - sec_now), 717 (int)context->max_skew); 718 goto out; 719 } 720 721 if (creds->times.starttime != 0 722 && tmp_time != creds->times.starttime) { 723 krb5_clear_error_message (context); 724 ret = KRB5KRB_AP_ERR_MODIFIED; 725 goto out; 726 } 727 728 creds->times.starttime = tmp_time; 729 730 if (rep->enc_part.renew_till) { 731 tmp_time = *rep->enc_part.renew_till; 732 } else 733 tmp_time = 0; 734 735 if (creds->times.renew_till != 0 736 && tmp_time > creds->times.renew_till) { 737 krb5_clear_error_message (context); 738 ret = KRB5KRB_AP_ERR_MODIFIED; 739 goto out; 740 } 741 742 creds->times.renew_till = tmp_time; 743 744 creds->times.authtime = rep->enc_part.authtime; 745 746 if (creds->times.endtime != 0 747 && rep->enc_part.endtime > creds->times.endtime) { 748 krb5_clear_error_message (context); 749 ret = KRB5KRB_AP_ERR_MODIFIED; 750 goto out; 751 } 752 753 creds->times.endtime = rep->enc_part.endtime; 754 755 if(rep->enc_part.caddr) 756 krb5_copy_addresses (context, rep->enc_part.caddr, &creds->addresses); 757 else if(addrs) 758 krb5_copy_addresses (context, addrs, &creds->addresses); 759 else { 760 creds->addresses.len = 0; 761 creds->addresses.val = NULL; 762 } 763 creds->flags.b = rep->enc_part.flags; 764 765 creds->authdata.len = 0; 766 creds->authdata.val = NULL; 767 768 /* extract ticket */ 769 ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length, 770 &rep->kdc_rep.ticket, &len, ret); 771 if(ret) 772 goto out; 773 if (creds->ticket.length != len) 774 krb5_abortx(context, "internal error in ASN.1 encoder"); 775 creds->second_ticket.length = 0; 776 creds->second_ticket.data = NULL; 777 778 779out: 780 memset (rep->enc_part.key.keyvalue.data, 0, 781 rep->enc_part.key.keyvalue.length); 782 return ret; 783} 784