Allow users to specify their own configuration file ~/.krb5/config
[heimdal.git] / lib / krb5 / ticket.c
blob0716411a01aa3d20bb014d8d6383cae1651f90a2
1 /*
2 * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
34 #include "krb5_locl.h"
36 /**
37 * Free ticket and content
39 * @param context a Kerberos 5 context
40 * @param ticket ticket to free
42 * @return Returns 0 to indicate success. Otherwise an kerberos et
43 * error code is returned, see krb5_get_error_message().
45 * @ingroup krb5
48 krb5_error_code KRB5_LIB_FUNCTION
49 krb5_free_ticket(krb5_context context,
50 krb5_ticket *ticket)
52 free_EncTicketPart(&ticket->ticket);
53 krb5_free_principal(context, ticket->client);
54 krb5_free_principal(context, ticket->server);
55 free(ticket);
56 return 0;
59 /**
60 * Copy ticket and content
62 * @param context a Kerberos 5 context
63 * @param from ticket to copy
64 * @param to new copy of ticket, free with krb5_free_ticket()
66 * @return Returns 0 to indicate success. Otherwise an kerberos et
67 * error code is returned, see krb5_get_error_message().
69 * @ingroup krb5
72 krb5_error_code KRB5_LIB_FUNCTION
73 krb5_copy_ticket(krb5_context context,
74 const krb5_ticket *from,
75 krb5_ticket **to)
77 krb5_error_code ret;
78 krb5_ticket *tmp;
80 *to = NULL;
81 tmp = malloc(sizeof(*tmp));
82 if(tmp == NULL) {
83 krb5_set_error_message(context, ENOMEM,
84 N_("malloc: out of memory", ""));
85 return ENOMEM;
87 if((ret = copy_EncTicketPart(&from->ticket, &tmp->ticket))){
88 free(tmp);
89 return ret;
91 ret = krb5_copy_principal(context, from->client, &tmp->client);
92 if(ret){
93 free_EncTicketPart(&tmp->ticket);
94 free(tmp);
95 return ret;
97 ret = krb5_copy_principal(context, from->server, &tmp->server);
98 if(ret){
99 krb5_free_principal(context, tmp->client);
100 free_EncTicketPart(&tmp->ticket);
101 free(tmp);
102 return ret;
104 *to = tmp;
105 return 0;
109 * Return client principal in ticket
111 * @param context a Kerberos 5 context
112 * @param ticket ticket to copy
113 * @param client client principal, free with krb5_free_principal()
115 * @return Returns 0 to indicate success. Otherwise an kerberos et
116 * error code is returned, see krb5_get_error_message().
118 * @ingroup krb5
121 krb5_error_code KRB5_LIB_FUNCTION
122 krb5_ticket_get_client(krb5_context context,
123 const krb5_ticket *ticket,
124 krb5_principal *client)
126 return krb5_copy_principal(context, ticket->client, client);
130 * Return server principal in ticket
132 * @param context a Kerberos 5 context
133 * @param ticket ticket to copy
134 * @param server server principal, free with krb5_free_principal()
136 * @return Returns 0 to indicate success. Otherwise an kerberos et
137 * error code is returned, see krb5_get_error_message().
139 * @ingroup krb5
142 krb5_error_code KRB5_LIB_FUNCTION
143 krb5_ticket_get_server(krb5_context context,
144 const krb5_ticket *ticket,
145 krb5_principal *server)
147 return krb5_copy_principal(context, ticket->server, server);
151 * Return end time of ticket
153 * @param context a Kerberos 5 context
154 * @param ticket ticket to copy
156 * @return end time of ticket
158 * @ingroup krb5
161 time_t KRB5_LIB_FUNCTION
162 krb5_ticket_get_endtime(krb5_context context,
163 const krb5_ticket *ticket)
165 return ticket->ticket.endtime;
169 * Get the flags from the Kerberos ticket
171 * @param context Kerberos context
172 * @param ticket Kerberos ticket
174 * @return ticket flags
176 * @ingroup krb5_ticket
178 unsigned long
179 krb5_ticket_get_flags(krb5_context context,
180 const krb5_ticket *ticket)
182 return TicketFlags2int(ticket->ticket.flags);
185 static int
186 find_type_in_ad(krb5_context context,
187 int type,
188 krb5_data *data,
189 krb5_boolean *found,
190 krb5_boolean failp,
191 krb5_keyblock *sessionkey,
192 const AuthorizationData *ad,
193 int level)
195 krb5_error_code ret = 0;
196 int i;
198 if (level > 9) {
199 ret = ENOENT; /* XXX */
200 krb5_set_error_message(context, ret,
201 N_("Authorization data nested deeper "
202 "then %d levels, stop searching", ""),
203 level);
204 goto out;
208 * Only copy out the element the first time we get to it, we need
209 * to run over the whole authorization data fields to check if
210 * there are any container clases we need to care about.
212 for (i = 0; i < ad->len; i++) {
213 if (!*found && ad->val[i].ad_type == type) {
214 ret = der_copy_octet_string(&ad->val[i].ad_data, data);
215 if (ret) {
216 krb5_set_error_message(context, ret,
217 N_("malloc: out of memory", ""));
218 goto out;
220 *found = TRUE;
221 continue;
223 switch (ad->val[i].ad_type) {
224 case KRB5_AUTHDATA_IF_RELEVANT: {
225 AuthorizationData child;
226 ret = decode_AuthorizationData(ad->val[i].ad_data.data,
227 ad->val[i].ad_data.length,
228 &child,
229 NULL);
230 if (ret) {
231 krb5_set_error_message(context, ret,
232 N_("Failed to decode "
233 "IF_RELEVANT with %d", ""),
234 (int)ret);
235 goto out;
237 ret = find_type_in_ad(context, type, data, found, FALSE,
238 sessionkey, &child, level + 1);
239 free_AuthorizationData(&child);
240 if (ret)
241 goto out;
242 break;
244 #if 0 /* XXX test */
245 case KRB5_AUTHDATA_KDC_ISSUED: {
246 AD_KDCIssued child;
248 ret = decode_AD_KDCIssued(ad->val[i].ad_data.data,
249 ad->val[i].ad_data.length,
250 &child,
251 NULL);
252 if (ret) {
253 krb5_set_error_message(context, ret,
254 N_("Failed to decode "
255 "AD_KDCIssued with %d", ""),
256 ret);
257 goto out;
259 if (failp) {
260 krb5_boolean valid;
261 krb5_data buf;
262 size_t len;
264 ASN1_MALLOC_ENCODE(AuthorizationData, buf.data, buf.length,
265 &child.elements, &len, ret);
266 if (ret) {
267 free_AD_KDCIssued(&child);
268 krb5_clear_error_message(context);
269 goto out;
271 if(buf.length != len)
272 krb5_abortx(context, "internal error in ASN.1 encoder");
274 ret = krb5_c_verify_checksum(context, sessionkey, 19, &buf,
275 &child.ad_checksum, &valid);
276 krb5_data_free(&buf);
277 if (ret) {
278 free_AD_KDCIssued(&child);
279 goto out;
281 if (!valid) {
282 krb5_clear_error_message(context);
283 ret = ENOENT;
284 free_AD_KDCIssued(&child);
285 goto out;
288 ret = find_type_in_ad(context, type, data, found, failp, sessionkey,
289 &child.elements, level + 1);
290 free_AD_KDCIssued(&child);
291 if (ret)
292 goto out;
293 break;
295 #endif
296 case KRB5_AUTHDATA_AND_OR:
297 if (!failp)
298 break;
299 ret = ENOENT; /* XXX */
300 krb5_set_error_message(context, ret,
301 N_("Authorization data contains "
302 "AND-OR element that is unknown to the "
303 "application", ""));
304 goto out;
305 default:
306 if (!failp)
307 break;
308 ret = ENOENT; /* XXX */
309 krb5_set_error_message(context, ret,
310 N_("Authorization data contains "
311 "unknown type (%d) ", ""),
312 ad->val[i].ad_type);
313 goto out;
316 out:
317 if (ret) {
318 if (*found) {
319 krb5_data_free(data);
320 *found = 0;
323 return ret;
327 * Extract the authorization data type of type from the ticket. Store
328 * the field in data. This function is to use for kerberos
329 * applications.
331 * @param context a Kerberos 5 context
332 * @param ticket Kerberos ticket
333 * @param type type to fetch
334 * @param data returned data, free with krb5_data_free()
336 * @ingroup krb5
339 krb5_error_code KRB5_LIB_FUNCTION
340 krb5_ticket_get_authorization_data_type(krb5_context context,
341 krb5_ticket *ticket,
342 int type,
343 krb5_data *data)
345 AuthorizationData *ad;
346 krb5_error_code ret;
347 krb5_boolean found = FALSE;
349 krb5_data_zero(data);
351 ad = ticket->ticket.authorization_data;
352 if (ticket->ticket.authorization_data == NULL) {
353 krb5_set_error_message(context, ENOENT,
354 N_("Ticket have not authorization data", ""));
355 return ENOENT; /* XXX */
358 ret = find_type_in_ad(context, type, data, &found, TRUE,
359 &ticket->ticket.key, ad, 0);
360 if (ret)
361 return ret;
362 if (!found) {
363 krb5_set_error_message(context, ENOENT,
364 N_("Ticket have not "
365 "authorization data of type %d", ""),
366 type);
367 return ENOENT; /* XXX */
369 return 0;
372 static krb5_error_code
373 check_server_referral(krb5_context context,
374 krb5_kdc_rep *rep,
375 unsigned flags,
376 krb5_const_principal requested,
377 krb5_const_principal returned,
378 krb5_keyblock * key)
380 krb5_error_code ret;
381 PA_ServerReferralData ref;
382 krb5_crypto session;
383 EncryptedData ed;
384 size_t len;
385 krb5_data data;
386 PA_DATA *pa;
387 int i = 0, cmp;
389 if (rep->kdc_rep.padata == NULL)
390 goto noreferral;
392 pa = krb5_find_padata(rep->kdc_rep.padata->val,
393 rep->kdc_rep.padata->len,
394 KRB5_PADATA_SERVER_REFERRAL, &i);
395 if (pa == NULL)
396 goto noreferral;
398 memset(&ed, 0, sizeof(ed));
399 memset(&ref, 0, sizeof(ref));
401 ret = decode_EncryptedData(pa->padata_value.data,
402 pa->padata_value.length,
403 &ed, &len);
404 if (ret)
405 return ret;
406 if (len != pa->padata_value.length) {
407 free_EncryptedData(&ed);
408 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
409 N_("Referral EncryptedData wrong for realm %s",
410 "realm"), requested->realm);
411 return KRB5KRB_AP_ERR_MODIFIED;
414 ret = krb5_crypto_init(context, key, 0, &session);
415 if (ret) {
416 free_EncryptedData(&ed);
417 return ret;
420 ret = krb5_decrypt_EncryptedData(context, session,
421 KRB5_KU_PA_SERVER_REFERRAL,
422 &ed, &data);
423 free_EncryptedData(&ed);
424 krb5_crypto_destroy(context, session);
425 if (ret)
426 return ret;
428 ret = decode_PA_ServerReferralData(data.data, data.length, &ref, &len);
429 if (ret) {
430 krb5_data_free(&data);
431 return ret;
433 krb5_data_free(&data);
435 if (strcmp(requested->realm, returned->realm) != 0) {
436 free_PA_ServerReferralData(&ref);
437 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
438 N_("server ref realm mismatch, "
439 "requested realm %s got back %s", ""),
440 requested->realm, returned->realm);
441 return KRB5KRB_AP_ERR_MODIFIED;
444 if (krb5_principal_is_krbtgt(context, returned)) {
445 const char *realm = returned->name.name_string.val[1];
447 if (ref.referred_realm == NULL
448 || strcmp(*ref.referred_realm, realm) != 0)
450 free_PA_ServerReferralData(&ref);
451 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
452 N_("tgt returned with wrong ref", ""));
453 return KRB5KRB_AP_ERR_MODIFIED;
455 } else if (krb5_principal_compare(context, returned, requested) == 0) {
456 free_PA_ServerReferralData(&ref);
457 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
458 N_("req princ no same as returned", ""));
459 return KRB5KRB_AP_ERR_MODIFIED;
462 if (ref.requested_principal_name) {
463 cmp = _krb5_principal_compare_PrincipalName(context,
464 requested,
465 ref.requested_principal_name);
466 if (!cmp) {
467 free_PA_ServerReferralData(&ref);
468 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
469 N_("referred principal not same "
470 "as requested", ""));
471 return KRB5KRB_AP_ERR_MODIFIED;
473 } else if (flags & EXTRACT_TICKET_AS_REQ) {
474 free_PA_ServerReferralData(&ref);
475 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
476 N_("Requested principal missing on AS-REQ", ""));
477 return KRB5KRB_AP_ERR_MODIFIED;
480 free_PA_ServerReferralData(&ref);
482 return ret;
483 noreferral:
485 * Expect excact match or that we got a krbtgt
487 if (krb5_principal_compare(context, requested, returned) != TRUE &&
488 (krb5_realm_compare(context, requested, returned) != TRUE &&
489 krb5_principal_is_krbtgt(context, returned) != TRUE))
491 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
492 N_("Not same server principal returned "
493 "as requested", ""));
494 return KRB5KRB_AP_ERR_MODIFIED;
496 return 0;
501 * Verify referral data
505 static krb5_error_code
506 check_client_referral(krb5_context context,
507 krb5_kdc_rep *rep,
508 krb5_const_principal requested,
509 krb5_const_principal mapped,
510 krb5_keyblock const * key)
512 krb5_error_code ret;
513 PA_ClientCanonicalized canon;
514 krb5_crypto crypto;
515 krb5_data data;
516 PA_DATA *pa;
517 size_t len;
518 int i = 0;
520 if (rep->kdc_rep.padata == NULL)
521 goto noreferral;
523 pa = krb5_find_padata(rep->kdc_rep.padata->val,
524 rep->kdc_rep.padata->len,
525 KRB5_PADATA_CLIENT_CANONICALIZED, &i);
526 if (pa == NULL)
527 goto noreferral;
529 ret = decode_PA_ClientCanonicalized(pa->padata_value.data,
530 pa->padata_value.length,
531 &canon, &len);
532 if (ret) {
533 krb5_set_error_message(context, ret,
534 N_("Failed to decode ClientCanonicalized "
535 "from realm %s", ""), requested->realm);
536 return ret;
539 ASN1_MALLOC_ENCODE(PA_ClientCanonicalizedNames, data.data, data.length,
540 &canon.names, &len, ret);
541 if (ret) {
542 free_PA_ClientCanonicalized(&canon);
543 return ret;
545 if (data.length != len)
546 krb5_abortx(context, "internal asn.1 error");
548 ret = krb5_crypto_init(context, key, 0, &crypto);
549 if (ret) {
550 free(data.data);
551 free_PA_ClientCanonicalized(&canon);
552 return ret;
555 ret = krb5_verify_checksum(context, crypto, KRB5_KU_CANONICALIZED_NAMES,
556 data.data, data.length,
557 &canon.canon_checksum);
558 krb5_crypto_destroy(context, crypto);
559 free(data.data);
560 if (ret) {
561 krb5_set_error_message(context, ret,
562 N_("Failed to verify client canonicalized "
563 "data from realm %s", ""),
564 requested->realm);
565 free_PA_ClientCanonicalized(&canon);
566 return ret;
569 if (!_krb5_principal_compare_PrincipalName(context,
570 requested,
571 &canon.names.requested_name))
573 free_PA_ClientCanonicalized(&canon);
574 krb5_set_error_message(context, KRB5_PRINC_NOMATCH,
575 N_("Requested name doesn't match"
576 " in client referral", ""));
577 return KRB5_PRINC_NOMATCH;
579 if (!_krb5_principal_compare_PrincipalName(context,
580 mapped,
581 &canon.names.mapped_name))
583 free_PA_ClientCanonicalized(&canon);
584 krb5_set_error_message(context, KRB5_PRINC_NOMATCH,
585 N_("Mapped name doesn't match"
586 " in client referral", ""));
587 return KRB5_PRINC_NOMATCH;
590 return 0;
592 noreferral:
593 if (krb5_principal_compare(context, requested, mapped) == FALSE) {
594 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
595 N_("Not same client principal returned "
596 "as requested", ""));
597 return KRB5KRB_AP_ERR_MODIFIED;
599 return 0;
603 static krb5_error_code
604 decrypt_tkt (krb5_context context,
605 krb5_keyblock *key,
606 krb5_key_usage usage,
607 krb5_const_pointer decrypt_arg,
608 krb5_kdc_rep *dec_rep)
610 krb5_error_code ret;
611 krb5_data data;
612 size_t size;
613 krb5_crypto crypto;
615 ret = krb5_crypto_init(context, key, 0, &crypto);
616 if (ret)
617 return ret;
619 ret = krb5_decrypt_EncryptedData (context,
620 crypto,
621 usage,
622 &dec_rep->kdc_rep.enc_part,
623 &data);
624 krb5_crypto_destroy(context, crypto);
626 if (ret)
627 return ret;
629 ret = decode_EncASRepPart(data.data,
630 data.length,
631 &dec_rep->enc_part,
632 &size);
633 if (ret)
634 ret = decode_EncTGSRepPart(data.data,
635 data.length,
636 &dec_rep->enc_part,
637 &size);
638 krb5_data_free (&data);
639 if (ret) {
640 krb5_set_error_message(context, ret,
641 N_("Failed to decode encpart in ticket", ""));
642 return ret;
644 return 0;
648 _krb5_extract_ticket(krb5_context context,
649 krb5_kdc_rep *rep,
650 krb5_creds *creds,
651 krb5_keyblock *key,
652 krb5_const_pointer keyseed,
653 krb5_key_usage key_usage,
654 krb5_addresses *addrs,
655 unsigned nonce,
656 unsigned flags,
657 krb5_decrypt_proc decrypt_proc,
658 krb5_const_pointer decryptarg)
660 krb5_error_code ret;
661 krb5_principal tmp_principal;
662 size_t len;
663 time_t tmp_time;
664 krb5_timestamp sec_now;
666 /* decrypt */
668 if (decrypt_proc == NULL)
669 decrypt_proc = decrypt_tkt;
671 ret = (*decrypt_proc)(context, key, key_usage, decryptarg, rep);
672 if (ret)
673 goto out;
675 /* save session key */
677 creds->session.keyvalue.length = 0;
678 creds->session.keyvalue.data = NULL;
679 creds->session.keytype = rep->enc_part.key.keytype;
680 ret = krb5_data_copy (&creds->session.keyvalue,
681 rep->enc_part.key.keyvalue.data,
682 rep->enc_part.key.keyvalue.length);
683 if (ret) {
684 krb5_clear_error_message(context);
685 goto out;
688 /* compare client and save */
689 ret = _krb5_principalname2krb5_principal (context,
690 &tmp_principal,
691 rep->kdc_rep.cname,
692 rep->kdc_rep.crealm);
693 if (ret)
694 goto out;
696 /* check client referral and save principal */
697 /* anonymous here ? */
698 if((flags & EXTRACT_TICKET_ALLOW_CNAME_MISMATCH) == 0) {
699 ret = check_client_referral(context, rep,
700 creds->client,
701 tmp_principal,
702 &creds->session);
703 if (ret) {
704 krb5_free_principal (context, tmp_principal);
705 goto out;
708 krb5_free_principal (context, creds->client);
709 creds->client = tmp_principal;
711 /* check server referral and save principal */
712 ret = _krb5_principalname2krb5_principal (context,
713 &tmp_principal,
714 rep->kdc_rep.ticket.sname,
715 rep->kdc_rep.ticket.realm);
716 if (ret)
717 goto out;
718 if((flags & EXTRACT_TICKET_ALLOW_SERVER_MISMATCH) == 0){
719 ret = check_server_referral(context,
720 rep,
721 flags,
722 creds->server,
723 tmp_principal,
724 &creds->session);
725 if (ret) {
726 krb5_free_principal (context, tmp_principal);
727 goto out;
730 krb5_free_principal(context, creds->server);
731 creds->server = tmp_principal;
733 /* verify names */
734 if(flags & EXTRACT_TICKET_MATCH_REALM){
735 const char *srealm = krb5_principal_get_realm(context, creds->server);
736 const char *crealm = krb5_principal_get_realm(context, creds->client);
738 if (strcmp(rep->enc_part.srealm, srealm) != 0 ||
739 strcmp(rep->enc_part.srealm, crealm) != 0)
741 ret = KRB5KRB_AP_ERR_MODIFIED;
742 krb5_clear_error_message(context);
743 goto out;
747 /* compare nonces */
749 if (nonce != rep->enc_part.nonce) {
750 ret = KRB5KRB_AP_ERR_MODIFIED;
751 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
752 goto out;
755 /* set kdc-offset */
757 krb5_timeofday (context, &sec_now);
758 if (rep->enc_part.flags.initial
759 && context->kdc_sec_offset == 0
760 && krb5_config_get_bool (context, NULL,
761 "libdefaults",
762 "kdc_timesync",
763 NULL)) {
764 context->kdc_sec_offset = rep->enc_part.authtime - sec_now;
765 krb5_timeofday (context, &sec_now);
768 /* check all times */
770 if (rep->enc_part.starttime) {
771 tmp_time = *rep->enc_part.starttime;
772 } else
773 tmp_time = rep->enc_part.authtime;
775 if (creds->times.starttime == 0
776 && abs(tmp_time - sec_now) > context->max_skew) {
777 ret = KRB5KRB_AP_ERR_SKEW;
778 krb5_set_error_message (context, ret,
779 N_("time skew (%d) larger than max (%d)", ""),
780 abs(tmp_time - sec_now),
781 (int)context->max_skew);
782 goto out;
785 if (creds->times.starttime != 0
786 && tmp_time != creds->times.starttime) {
787 krb5_clear_error_message (context);
788 ret = KRB5KRB_AP_ERR_MODIFIED;
789 goto out;
792 creds->times.starttime = tmp_time;
794 if (rep->enc_part.renew_till) {
795 tmp_time = *rep->enc_part.renew_till;
796 } else
797 tmp_time = 0;
799 if (creds->times.renew_till != 0
800 && tmp_time > creds->times.renew_till) {
801 krb5_clear_error_message (context);
802 ret = KRB5KRB_AP_ERR_MODIFIED;
803 goto out;
806 creds->times.renew_till = tmp_time;
808 creds->times.authtime = rep->enc_part.authtime;
810 if (creds->times.endtime != 0
811 && rep->enc_part.endtime > creds->times.endtime) {
812 krb5_clear_error_message (context);
813 ret = KRB5KRB_AP_ERR_MODIFIED;
814 goto out;
817 creds->times.endtime = rep->enc_part.endtime;
819 if(rep->enc_part.caddr)
820 krb5_copy_addresses (context, rep->enc_part.caddr, &creds->addresses);
821 else if(addrs)
822 krb5_copy_addresses (context, addrs, &creds->addresses);
823 else {
824 creds->addresses.len = 0;
825 creds->addresses.val = NULL;
827 creds->flags.b = rep->enc_part.flags;
829 creds->authdata.len = 0;
830 creds->authdata.val = NULL;
832 /* extract ticket */
833 ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length,
834 &rep->kdc_rep.ticket, &len, ret);
835 if(ret)
836 goto out;
837 if (creds->ticket.length != len)
838 krb5_abortx(context, "internal error in ASN.1 encoder");
839 creds->second_ticket.length = 0;
840 creds->second_ticket.data = NULL;
843 out:
844 memset (rep->enc_part.key.keyvalue.data, 0,
845 rep->enc_part.key.keyvalue.length);
846 return ret;