Merge pull request #203 from sdigit/patch-1
[heimdal.git] / lib / krb5 / ticket.c
blobd95d96d1b68b12d674c3de77e1e1f20496038427
1 /*
2 * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
36 #include "krb5_locl.h"
38 /**
39 * Free ticket and content
41 * @param context a Kerberos 5 context
42 * @param ticket ticket to free
44 * @return Returns 0 to indicate success. Otherwise an kerberos et
45 * error code is returned, see krb5_get_error_message().
47 * @ingroup krb5
50 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
51 krb5_free_ticket(krb5_context context,
52 krb5_ticket *ticket)
54 free_EncTicketPart(&ticket->ticket);
55 krb5_free_principal(context, ticket->client);
56 krb5_free_principal(context, ticket->server);
57 free(ticket);
58 return 0;
61 /**
62 * Copy ticket and content
64 * @param context a Kerberos 5 context
65 * @param from ticket to copy
66 * @param to new copy of ticket, free with krb5_free_ticket()
68 * @return Returns 0 to indicate success. Otherwise an kerberos et
69 * error code is returned, see krb5_get_error_message().
71 * @ingroup krb5
74 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
75 krb5_copy_ticket(krb5_context context,
76 const krb5_ticket *from,
77 krb5_ticket **to)
79 krb5_error_code ret;
80 krb5_ticket *tmp;
82 *to = NULL;
83 tmp = malloc(sizeof(*tmp));
84 if (tmp == NULL)
85 return krb5_enomem(context);
86 if((ret = copy_EncTicketPart(&from->ticket, &tmp->ticket))){
87 free(tmp);
88 return ret;
90 ret = krb5_copy_principal(context, from->client, &tmp->client);
91 if(ret){
92 free_EncTicketPart(&tmp->ticket);
93 free(tmp);
94 return ret;
96 ret = krb5_copy_principal(context, from->server, &tmp->server);
97 if(ret){
98 krb5_free_principal(context, tmp->client);
99 free_EncTicketPart(&tmp->ticket);
100 free(tmp);
101 return ret;
103 *to = tmp;
104 return 0;
108 * Return client principal in ticket
110 * @param context a Kerberos 5 context
111 * @param ticket ticket to copy
112 * @param client client principal, free with krb5_free_principal()
114 * @return Returns 0 to indicate success. Otherwise an kerberos et
115 * error code is returned, see krb5_get_error_message().
117 * @ingroup krb5
120 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
121 krb5_ticket_get_client(krb5_context context,
122 const krb5_ticket *ticket,
123 krb5_principal *client)
125 return krb5_copy_principal(context, ticket->client, client);
129 * Return server principal in ticket
131 * @param context a Kerberos 5 context
132 * @param ticket ticket to copy
133 * @param server server principal, free with krb5_free_principal()
135 * @return Returns 0 to indicate success. Otherwise an kerberos et
136 * error code is returned, see krb5_get_error_message().
138 * @ingroup krb5
141 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
142 krb5_ticket_get_server(krb5_context context,
143 const krb5_ticket *ticket,
144 krb5_principal *server)
146 return krb5_copy_principal(context, ticket->server, server);
150 * Return end time of ticket
152 * @param context a Kerberos 5 context
153 * @param ticket ticket to copy
155 * @return end time of ticket
157 * @ingroup krb5
160 KRB5_LIB_FUNCTION time_t KRB5_LIB_CALL
161 krb5_ticket_get_endtime(krb5_context context,
162 const krb5_ticket *ticket)
164 return ticket->ticket.endtime;
168 * Get the flags from the Kerberos ticket
170 * @param context Kerberos context
171 * @param ticket Kerberos ticket
173 * @return ticket flags
175 * @ingroup krb5_ticket
177 KRB5_LIB_FUNCTION unsigned long KRB5_LIB_CALL
178 krb5_ticket_get_flags(krb5_context context,
179 const krb5_ticket *ticket)
181 return TicketFlags2int(ticket->ticket.flags);
184 static int
185 find_type_in_ad(krb5_context context,
186 int type,
187 krb5_data *data,
188 krb5_boolean *found,
189 krb5_boolean failp,
190 krb5_keyblock *sessionkey,
191 const AuthorizationData *ad,
192 int level)
194 krb5_error_code ret = 0;
195 size_t i;
197 if (level > 9) {
198 ret = ENOENT; /* XXX */
199 krb5_set_error_message(context, ret,
200 N_("Authorization data nested deeper "
201 "then %d levels, stop searching", ""),
202 level);
203 goto out;
207 * Only copy out the element the first time we get to it, we need
208 * to run over the whole authorization data fields to check if
209 * there are any container clases we need to care about.
211 for (i = 0; i < ad->len; i++) {
212 if (!*found && ad->val[i].ad_type == type) {
213 ret = der_copy_octet_string(&ad->val[i].ad_data, data);
214 if (ret) {
215 krb5_set_error_message(context, ret,
216 N_("malloc: out of memory", ""));
217 goto out;
219 *found = TRUE;
220 continue;
222 switch (ad->val[i].ad_type) {
223 case KRB5_AUTHDATA_IF_RELEVANT: {
224 AuthorizationData child;
225 ret = decode_AuthorizationData(ad->val[i].ad_data.data,
226 ad->val[i].ad_data.length,
227 &child,
228 NULL);
229 if (ret) {
230 krb5_set_error_message(context, ret,
231 N_("Failed to decode "
232 "IF_RELEVANT with %d", ""),
233 (int)ret);
234 goto out;
236 ret = find_type_in_ad(context, type, data, found, FALSE,
237 sessionkey, &child, level + 1);
238 free_AuthorizationData(&child);
239 if (ret)
240 goto out;
241 break;
243 #if 0 /* XXX test */
244 case KRB5_AUTHDATA_KDC_ISSUED: {
245 AD_KDCIssued child;
247 ret = decode_AD_KDCIssued(ad->val[i].ad_data.data,
248 ad->val[i].ad_data.length,
249 &child,
250 NULL);
251 if (ret) {
252 krb5_set_error_message(context, ret,
253 N_("Failed to decode "
254 "AD_KDCIssued with %d", ""),
255 ret);
256 goto out;
258 if (failp) {
259 krb5_boolean valid;
260 krb5_data buf;
261 size_t len;
263 ASN1_MALLOC_ENCODE(AuthorizationData, buf.data, buf.length,
264 &child.elements, &len, ret);
265 if (ret) {
266 free_AD_KDCIssued(&child);
267 krb5_clear_error_message(context);
268 goto out;
270 if(buf.length != len)
271 krb5_abortx(context, "internal error in ASN.1 encoder");
273 ret = krb5_c_verify_checksum(context, sessionkey, 19, &buf,
274 &child.ad_checksum, &valid);
275 krb5_data_free(&buf);
276 if (ret) {
277 free_AD_KDCIssued(&child);
278 goto out;
280 if (!valid) {
281 krb5_clear_error_message(context);
282 ret = ENOENT;
283 free_AD_KDCIssued(&child);
284 goto out;
287 ret = find_type_in_ad(context, type, data, found, failp, sessionkey,
288 &child.elements, level + 1);
289 free_AD_KDCIssued(&child);
290 if (ret)
291 goto out;
292 break;
294 #endif
295 case KRB5_AUTHDATA_AND_OR:
296 if (!failp)
297 break;
298 ret = ENOENT; /* XXX */
299 krb5_set_error_message(context, ret,
300 N_("Authorization data contains "
301 "AND-OR element that is unknown to the "
302 "application", ""));
303 goto out;
304 default:
305 if (!failp)
306 break;
307 ret = ENOENT; /* XXX */
308 krb5_set_error_message(context, ret,
309 N_("Authorization data contains "
310 "unknown type (%d) ", ""),
311 ad->val[i].ad_type);
312 goto out;
315 out:
316 if (ret) {
317 if (*found) {
318 krb5_data_free(data);
319 *found = 0;
322 return ret;
325 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
326 _krb5_get_ad(krb5_context context,
327 const AuthorizationData *ad,
328 krb5_keyblock *sessionkey,
329 int type,
330 krb5_data *data)
332 krb5_boolean found = FALSE;
333 krb5_error_code ret;
335 krb5_data_zero(data);
337 if (ad == NULL) {
338 krb5_set_error_message(context, ENOENT,
339 N_("No authorization data", ""));
340 return ENOENT; /* XXX */
343 ret = find_type_in_ad(context, type, data, &found, TRUE, sessionkey, ad, 0);
344 if (ret)
345 return ret;
346 if (!found) {
347 krb5_set_error_message(context, ENOENT,
348 N_("Have no authorization data of type %d", ""),
349 type);
350 return ENOENT; /* XXX */
352 return 0;
357 * Extract the authorization data type of type from the ticket. Store
358 * the field in data. This function is to use for kerberos
359 * applications.
361 * @param context a Kerberos 5 context
362 * @param ticket Kerberos ticket
363 * @param type type to fetch
364 * @param data returned data, free with krb5_data_free()
366 * @ingroup krb5
369 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
370 krb5_ticket_get_authorization_data_type(krb5_context context,
371 krb5_ticket *ticket,
372 int type,
373 krb5_data *data)
375 AuthorizationData *ad;
376 krb5_error_code ret;
377 krb5_boolean found = FALSE;
379 krb5_data_zero(data);
381 ad = ticket->ticket.authorization_data;
382 if (ticket->ticket.authorization_data == NULL) {
383 krb5_set_error_message(context, ENOENT,
384 N_("Ticket have not authorization data", ""));
385 return ENOENT; /* XXX */
388 ret = find_type_in_ad(context, type, data, &found, TRUE,
389 &ticket->ticket.key, ad, 0);
390 if (ret)
391 return ret;
392 if (!found) {
393 krb5_set_error_message(context, ENOENT,
394 N_("Ticket have not "
395 "authorization data of type %d", ""),
396 type);
397 return ENOENT; /* XXX */
399 return 0;
402 static krb5_error_code
403 check_server_referral(krb5_context context,
404 krb5_kdc_rep *rep,
405 unsigned flags,
406 krb5_const_principal requested,
407 krb5_const_principal returned,
408 krb5_keyblock * key)
410 krb5_error_code ret;
411 PA_ServerReferralData ref;
412 krb5_crypto session;
413 EncryptedData ed;
414 size_t len;
415 krb5_data data;
416 PA_DATA *pa;
417 int i = 0, cmp;
419 if (rep->kdc_rep.padata == NULL)
420 goto noreferral;
422 pa = krb5_find_padata(rep->kdc_rep.padata->val,
423 rep->kdc_rep.padata->len,
424 KRB5_PADATA_SERVER_REFERRAL, &i);
425 if (pa == NULL)
426 goto noreferral;
428 memset(&ed, 0, sizeof(ed));
429 memset(&ref, 0, sizeof(ref));
431 ret = decode_EncryptedData(pa->padata_value.data,
432 pa->padata_value.length,
433 &ed, &len);
434 if (ret)
435 return ret;
436 if (len != pa->padata_value.length) {
437 free_EncryptedData(&ed);
438 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
439 N_("Referral EncryptedData wrong for realm %s",
440 "realm"), requested->realm);
441 return KRB5KRB_AP_ERR_MODIFIED;
444 ret = krb5_crypto_init(context, key, 0, &session);
445 if (ret) {
446 free_EncryptedData(&ed);
447 return ret;
450 ret = krb5_decrypt_EncryptedData(context, session,
451 KRB5_KU_PA_SERVER_REFERRAL,
452 &ed, &data);
453 free_EncryptedData(&ed);
454 krb5_crypto_destroy(context, session);
455 if (ret)
456 return ret;
458 ret = decode_PA_ServerReferralData(data.data, data.length, &ref, &len);
459 if (ret) {
460 krb5_data_free(&data);
461 return ret;
463 krb5_data_free(&data);
465 if (strcmp(requested->realm, returned->realm) != 0) {
466 free_PA_ServerReferralData(&ref);
467 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
468 N_("server ref realm mismatch, "
469 "requested realm %s got back %s", ""),
470 requested->realm, returned->realm);
471 return KRB5KRB_AP_ERR_MODIFIED;
474 if (krb5_principal_is_krbtgt(context, returned)) {
475 const char *realm = returned->name.name_string.val[1];
477 if (ref.referred_realm == NULL
478 || strcmp(*ref.referred_realm, realm) != 0)
480 free_PA_ServerReferralData(&ref);
481 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
482 N_("tgt returned with wrong ref", ""));
483 return KRB5KRB_AP_ERR_MODIFIED;
485 } else if (krb5_principal_compare(context, returned, requested) == 0) {
486 free_PA_ServerReferralData(&ref);
487 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
488 N_("req princ no same as returned", ""));
489 return KRB5KRB_AP_ERR_MODIFIED;
492 if (ref.requested_principal_name) {
493 cmp = _krb5_principal_compare_PrincipalName(context,
494 requested,
495 ref.requested_principal_name);
496 if (!cmp) {
497 free_PA_ServerReferralData(&ref);
498 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
499 N_("referred principal not same "
500 "as requested", ""));
501 return KRB5KRB_AP_ERR_MODIFIED;
503 } else if (flags & EXTRACT_TICKET_AS_REQ) {
504 free_PA_ServerReferralData(&ref);
505 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
506 N_("Requested principal missing on AS-REQ", ""));
507 return KRB5KRB_AP_ERR_MODIFIED;
510 free_PA_ServerReferralData(&ref);
512 return ret;
513 noreferral:
515 * Expect excact match or that we got a krbtgt
517 if (krb5_principal_compare(context, requested, returned) != TRUE &&
518 (krb5_realm_compare(context, requested, returned) != TRUE &&
519 krb5_principal_is_krbtgt(context, returned) != TRUE))
521 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
522 N_("Not same server principal returned "
523 "as requested", ""));
524 return KRB5KRB_AP_ERR_MODIFIED;
526 return 0;
531 * Verify referral data
535 static krb5_error_code
536 check_client_referral(krb5_context context,
537 krb5_kdc_rep *rep,
538 krb5_const_principal requested,
539 krb5_const_principal mapped,
540 krb5_keyblock const * key)
542 if (krb5_principal_compare(context, requested, mapped) == FALSE &&
543 !rep->enc_part.flags.enc_pa_rep)
545 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
546 N_("Not same client principal returned "
547 "as requested", ""));
548 return KRB5KRB_AP_ERR_MODIFIED;
550 return 0;
554 static krb5_error_code KRB5_CALLCONV
555 decrypt_tkt (krb5_context context,
556 krb5_keyblock *key,
557 krb5_key_usage usage,
558 krb5_const_pointer decrypt_arg,
559 krb5_kdc_rep *dec_rep)
561 krb5_error_code ret;
562 krb5_data data;
563 size_t size;
564 krb5_crypto crypto;
566 ret = krb5_crypto_init(context, key, 0, &crypto);
567 if (ret)
568 return ret;
570 ret = krb5_decrypt_EncryptedData (context,
571 crypto,
572 usage,
573 &dec_rep->kdc_rep.enc_part,
574 &data);
575 krb5_crypto_destroy(context, crypto);
577 if (ret)
578 return ret;
580 ret = decode_EncASRepPart(data.data,
581 data.length,
582 &dec_rep->enc_part,
583 &size);
584 if (ret)
585 ret = decode_EncTGSRepPart(data.data,
586 data.length,
587 &dec_rep->enc_part,
588 &size);
589 krb5_data_free (&data);
590 if (ret) {
591 krb5_set_error_message(context, ret,
592 N_("Failed to decode encpart in ticket", ""));
593 return ret;
595 return 0;
598 KRB5_LIB_FUNCTION int KRB5_LIB_CALL
599 _krb5_extract_ticket(krb5_context context,
600 krb5_kdc_rep *rep,
601 krb5_creds *creds,
602 krb5_keyblock *key,
603 krb5_const_pointer keyseed,
604 krb5_key_usage key_usage,
605 krb5_addresses *addrs,
606 unsigned nonce,
607 unsigned flags,
608 krb5_data *request,
609 krb5_decrypt_proc decrypt_proc,
610 krb5_const_pointer decryptarg)
612 krb5_error_code ret;
613 krb5_principal tmp_principal;
614 size_t len = 0;
615 time_t tmp_time;
616 krb5_timestamp sec_now;
618 /* decrypt */
620 if (decrypt_proc == NULL)
621 decrypt_proc = decrypt_tkt;
623 ret = (*decrypt_proc)(context, key, key_usage, decryptarg, rep);
624 if (ret)
625 goto out;
627 if (rep->enc_part.flags.enc_pa_rep && request) {
628 krb5_crypto crypto = NULL;
629 Checksum cksum;
630 PA_DATA *pa = NULL;
631 int idx = 0;
633 _krb5_debug(context, 5, "processing enc-ap-rep");
635 if (rep->enc_part.encrypted_pa_data == NULL ||
636 (pa = krb5_find_padata(rep->enc_part.encrypted_pa_data->val,
637 rep->enc_part.encrypted_pa_data->len,
638 KRB5_PADATA_REQ_ENC_PA_REP,
639 &idx)) == NULL)
641 _krb5_debug(context, 5, "KRB5_PADATA_REQ_ENC_PA_REP missing");
642 ret = KRB5KRB_AP_ERR_MODIFIED;
643 goto out;
646 ret = krb5_crypto_init(context, key, 0, &crypto);
647 if (ret)
648 goto out;
650 ret = decode_Checksum(pa->padata_value.data,
651 pa->padata_value.length,
652 &cksum, NULL);
653 if (ret) {
654 krb5_crypto_destroy(context, crypto);
655 goto out;
658 ret = krb5_verify_checksum(context, crypto,
659 KRB5_KU_AS_REQ,
660 request->data, request->length,
661 &cksum);
662 krb5_crypto_destroy(context, crypto);
663 free_Checksum(&cksum);
664 _krb5_debug(context, 5, "enc-ap-rep: %svalid", (ret == 0) ? "" : "in");
665 if (ret)
666 goto out;
669 /* save session key */
671 creds->session.keyvalue.length = 0;
672 creds->session.keyvalue.data = NULL;
673 creds->session.keytype = rep->enc_part.key.keytype;
674 ret = krb5_data_copy (&creds->session.keyvalue,
675 rep->enc_part.key.keyvalue.data,
676 rep->enc_part.key.keyvalue.length);
677 if (ret) {
678 krb5_clear_error_message(context);
679 goto out;
682 /* compare client and save */
683 ret = _krb5_principalname2krb5_principal(context,
684 &tmp_principal,
685 rep->kdc_rep.cname,
686 rep->kdc_rep.crealm);
687 if (ret)
688 goto out;
690 /* check client referral and save principal */
691 /* anonymous here ? */
692 if((flags & EXTRACT_TICKET_ALLOW_CNAME_MISMATCH) == 0) {
693 ret = check_client_referral(context, rep,
694 creds->client,
695 tmp_principal,
696 &creds->session);
697 if (ret) {
698 krb5_free_principal (context, tmp_principal);
699 goto out;
702 krb5_free_principal (context, creds->client);
703 creds->client = tmp_principal;
705 /* check server referral and save principal */
706 ret = _krb5_principalname2krb5_principal (context,
707 &tmp_principal,
708 rep->kdc_rep.ticket.sname,
709 rep->kdc_rep.ticket.realm);
710 if (ret)
711 goto out;
712 if((flags & EXTRACT_TICKET_ALLOW_SERVER_MISMATCH) == 0){
713 ret = check_server_referral(context,
714 rep,
715 flags,
716 creds->server,
717 tmp_principal,
718 &creds->session);
719 if (ret) {
720 krb5_free_principal (context, tmp_principal);
721 goto out;
724 krb5_free_principal(context, creds->server);
725 creds->server = tmp_principal;
727 /* verify names */
728 if(flags & EXTRACT_TICKET_MATCH_REALM){
729 const char *srealm = krb5_principal_get_realm(context, creds->server);
730 const char *crealm = krb5_principal_get_realm(context, creds->client);
732 if (strcmp(rep->enc_part.srealm, srealm) != 0 ||
733 strcmp(rep->enc_part.srealm, crealm) != 0)
735 ret = KRB5KRB_AP_ERR_MODIFIED;
736 krb5_clear_error_message(context);
737 goto out;
741 /* compare nonces */
743 if (nonce != (unsigned)rep->enc_part.nonce) {
744 ret = KRB5KRB_AP_ERR_MODIFIED;
745 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
746 goto out;
749 /* set kdc-offset */
751 krb5_timeofday (context, &sec_now);
752 if (rep->enc_part.flags.initial
753 && (flags & EXTRACT_TICKET_TIMESYNC)
754 && context->kdc_sec_offset == 0
755 && krb5_config_get_bool (context, NULL,
756 "libdefaults",
757 "kdc_timesync",
758 NULL)) {
759 context->kdc_sec_offset = rep->enc_part.authtime - sec_now;
760 krb5_timeofday (context, &sec_now);
763 /* check all times */
765 if (rep->enc_part.starttime) {
766 tmp_time = *rep->enc_part.starttime;
767 } else
768 tmp_time = rep->enc_part.authtime;
770 if (creds->times.starttime == 0
771 && labs(tmp_time - sec_now) > context->max_skew) {
772 ret = KRB5KRB_AP_ERR_SKEW;
773 krb5_set_error_message (context, ret,
774 N_("time skew (%ld) larger than max (%ld)", ""),
775 labs(tmp_time - sec_now),
776 (long)context->max_skew);
777 goto out;
780 if (creds->times.starttime != 0
781 && tmp_time != creds->times.starttime) {
782 krb5_clear_error_message (context);
783 ret = KRB5KRB_AP_ERR_MODIFIED;
784 goto out;
787 creds->times.starttime = tmp_time;
789 if (rep->enc_part.renew_till) {
790 tmp_time = *rep->enc_part.renew_till;
791 } else
792 tmp_time = 0;
794 if (creds->times.renew_till != 0
795 && tmp_time > creds->times.renew_till) {
796 krb5_clear_error_message (context);
797 ret = KRB5KRB_AP_ERR_MODIFIED;
798 goto out;
801 creds->times.renew_till = tmp_time;
803 creds->times.authtime = rep->enc_part.authtime;
805 if (creds->times.endtime != 0
806 && rep->enc_part.endtime > creds->times.endtime) {
807 krb5_clear_error_message (context);
808 ret = KRB5KRB_AP_ERR_MODIFIED;
809 goto out;
812 creds->times.endtime = rep->enc_part.endtime;
814 if(rep->enc_part.caddr)
815 krb5_copy_addresses (context, rep->enc_part.caddr, &creds->addresses);
816 else if(addrs)
817 krb5_copy_addresses (context, addrs, &creds->addresses);
818 else {
819 creds->addresses.len = 0;
820 creds->addresses.val = NULL;
822 creds->flags.b = rep->enc_part.flags;
824 creds->authdata.len = 0;
825 creds->authdata.val = NULL;
827 /* extract ticket */
828 ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length,
829 &rep->kdc_rep.ticket, &len, ret);
830 if(ret)
831 goto out;
832 if (creds->ticket.length != len)
833 krb5_abortx(context, "internal error in ASN.1 encoder");
834 creds->second_ticket.length = 0;
835 creds->second_ticket.data = NULL;
838 out:
839 memset (rep->enc_part.key.keyvalue.data, 0,
840 rep->enc_part.key.keyvalue.length);
841 return ret;