s4:heimdal: import lorikeet-heimdal-200909210500 (commit 290db8d23647a27c39b97c189a0b...
[Samba.git] / source4 / heimdal / lib / krb5 / ticket.c
blob3bd93879067192e5ca27487dbc7902bc12d054f2
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 (returned->name.name_string.len == 2 &&
445 strcmp(returned->name.name_string.val[0], KRB5_TGS_NAME) == 0)
447 const char *realm = returned->name.name_string.val[1];
449 if (ref.referred_realm == NULL
450 || strcmp(*ref.referred_realm, realm) != 0)
452 free_PA_ServerReferralData(&ref);
453 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
454 N_("tgt returned with wrong ref", ""));
455 return KRB5KRB_AP_ERR_MODIFIED;
457 } else if (krb5_principal_compare(context, returned, requested) == 0) {
458 free_PA_ServerReferralData(&ref);
459 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
460 N_("req princ no same as returned", ""));
461 return KRB5KRB_AP_ERR_MODIFIED;
464 if (ref.requested_principal_name) {
465 cmp = _krb5_principal_compare_PrincipalName(context,
466 requested,
467 ref.requested_principal_name);
468 if (!cmp) {
469 free_PA_ServerReferralData(&ref);
470 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
471 N_("referred principal not same "
472 "as requested", ""));
473 return KRB5KRB_AP_ERR_MODIFIED;
475 } else if (flags & EXTRACT_TICKET_AS_REQ) {
476 free_PA_ServerReferralData(&ref);
477 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
478 N_("Requested principal missing on AS-REQ", ""));
479 return KRB5KRB_AP_ERR_MODIFIED;
482 free_PA_ServerReferralData(&ref);
484 return ret;
485 noreferral:
486 if (krb5_principal_compare(context, requested, returned) == FALSE) {
487 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
488 N_("Not same server principal returned "
489 "as requested", ""));
490 return KRB5KRB_AP_ERR_MODIFIED;
492 return 0;
497 * Verify referral data
501 static krb5_error_code
502 check_client_referral(krb5_context context,
503 krb5_kdc_rep *rep,
504 krb5_const_principal requested,
505 krb5_const_principal mapped,
506 krb5_keyblock const * key)
508 krb5_error_code ret;
509 PA_ClientCanonicalized canon;
510 krb5_crypto crypto;
511 krb5_data data;
512 PA_DATA *pa;
513 size_t len;
514 int i = 0;
516 if (rep->kdc_rep.padata == NULL)
517 goto noreferral;
519 pa = krb5_find_padata(rep->kdc_rep.padata->val,
520 rep->kdc_rep.padata->len,
521 KRB5_PADATA_CLIENT_CANONICALIZED, &i);
522 if (pa == NULL)
523 goto noreferral;
525 ret = decode_PA_ClientCanonicalized(pa->padata_value.data,
526 pa->padata_value.length,
527 &canon, &len);
528 if (ret) {
529 krb5_set_error_message(context, ret,
530 N_("Failed to decode ClientCanonicalized "
531 "from realm %s", ""), requested->realm);
532 return ret;
535 ASN1_MALLOC_ENCODE(PA_ClientCanonicalizedNames, data.data, data.length,
536 &canon.names, &len, ret);
537 if (ret) {
538 free_PA_ClientCanonicalized(&canon);
539 return ret;
541 if (data.length != len)
542 krb5_abortx(context, "internal asn.1 error");
544 ret = krb5_crypto_init(context, key, 0, &crypto);
545 if (ret) {
546 free(data.data);
547 free_PA_ClientCanonicalized(&canon);
548 return ret;
551 ret = krb5_verify_checksum(context, crypto, KRB5_KU_CANONICALIZED_NAMES,
552 data.data, data.length,
553 &canon.canon_checksum);
554 krb5_crypto_destroy(context, crypto);
555 free(data.data);
556 if (ret) {
557 krb5_set_error_message(context, ret,
558 N_("Failed to verify client canonicalized "
559 "data from realm %s", ""),
560 requested->realm);
561 free_PA_ClientCanonicalized(&canon);
562 return ret;
565 if (!_krb5_principal_compare_PrincipalName(context,
566 requested,
567 &canon.names.requested_name))
569 free_PA_ClientCanonicalized(&canon);
570 krb5_set_error_message(context, KRB5_PRINC_NOMATCH,
571 N_("Requested name doesn't match"
572 " in client referral", ""));
573 return KRB5_PRINC_NOMATCH;
575 if (!_krb5_principal_compare_PrincipalName(context,
576 mapped,
577 &canon.names.mapped_name))
579 free_PA_ClientCanonicalized(&canon);
580 krb5_set_error_message(context, KRB5_PRINC_NOMATCH,
581 N_("Mapped name doesn't match"
582 " in client referral", ""));
583 return KRB5_PRINC_NOMATCH;
586 return 0;
588 noreferral:
589 if (krb5_principal_compare(context, requested, mapped) == FALSE) {
590 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
591 N_("Not same client principal returned "
592 "as requested", ""));
593 return KRB5KRB_AP_ERR_MODIFIED;
595 return 0;
599 static krb5_error_code
600 decrypt_tkt (krb5_context context,
601 krb5_keyblock *key,
602 krb5_key_usage usage,
603 krb5_const_pointer decrypt_arg,
604 krb5_kdc_rep *dec_rep)
606 krb5_error_code ret;
607 krb5_data data;
608 size_t size;
609 krb5_crypto crypto;
611 ret = krb5_crypto_init(context, key, 0, &crypto);
612 if (ret)
613 return ret;
615 ret = krb5_decrypt_EncryptedData (context,
616 crypto,
617 usage,
618 &dec_rep->kdc_rep.enc_part,
619 &data);
620 krb5_crypto_destroy(context, crypto);
622 if (ret)
623 return ret;
625 ret = decode_EncASRepPart(data.data,
626 data.length,
627 &dec_rep->enc_part,
628 &size);
629 if (ret)
630 ret = decode_EncTGSRepPart(data.data,
631 data.length,
632 &dec_rep->enc_part,
633 &size);
634 krb5_data_free (&data);
635 if (ret) {
636 krb5_set_error_message(context, ret,
637 N_("Failed to decode encpart in ticket", ""));
638 return ret;
640 return 0;
644 _krb5_extract_ticket(krb5_context context,
645 krb5_kdc_rep *rep,
646 krb5_creds *creds,
647 krb5_keyblock *key,
648 krb5_const_pointer keyseed,
649 krb5_key_usage key_usage,
650 krb5_addresses *addrs,
651 unsigned nonce,
652 unsigned flags,
653 krb5_decrypt_proc decrypt_proc,
654 krb5_const_pointer decryptarg)
656 krb5_error_code ret;
657 krb5_principal tmp_principal;
658 size_t len;
659 time_t tmp_time;
660 krb5_timestamp sec_now;
662 /* decrypt */
664 if (decrypt_proc == NULL)
665 decrypt_proc = decrypt_tkt;
667 ret = (*decrypt_proc)(context, key, key_usage, decryptarg, rep);
668 if (ret)
669 goto out;
671 /* save session key */
673 creds->session.keyvalue.length = 0;
674 creds->session.keyvalue.data = NULL;
675 creds->session.keytype = rep->enc_part.key.keytype;
676 ret = krb5_data_copy (&creds->session.keyvalue,
677 rep->enc_part.key.keyvalue.data,
678 rep->enc_part.key.keyvalue.length);
679 if (ret) {
680 krb5_clear_error_message(context);
681 goto out;
685 * HACK:
686 * this is really a ugly hack, to support using the Netbios Domain Name
687 * as realm against windows KDC's, they always return the full realm
688 * based on the DNS Name.
690 flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH;
691 flags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH;
693 /* compare client and save */
694 ret = _krb5_principalname2krb5_principal (context,
695 &tmp_principal,
696 rep->kdc_rep.cname,
697 rep->kdc_rep.crealm);
698 if (ret)
699 goto out;
701 /* check client referral and save principal */
702 /* anonymous here ? */
703 if((flags & EXTRACT_TICKET_ALLOW_CNAME_MISMATCH) == 0) {
704 ret = check_client_referral(context, rep,
705 creds->client,
706 tmp_principal,
707 &creds->session);
708 if (ret) {
709 krb5_free_principal (context, tmp_principal);
710 goto out;
713 krb5_free_principal (context, creds->client);
714 creds->client = tmp_principal;
716 /* check server referral and save principal */
717 ret = _krb5_principalname2krb5_principal (context,
718 &tmp_principal,
719 rep->kdc_rep.ticket.sname,
720 rep->kdc_rep.ticket.realm);
721 if (ret)
722 goto out;
723 if((flags & EXTRACT_TICKET_ALLOW_SERVER_MISMATCH) == 0){
724 ret = check_server_referral(context,
725 rep,
726 flags,
727 creds->server,
728 tmp_principal,
729 &creds->session);
730 if (ret) {
731 krb5_free_principal (context, tmp_principal);
732 goto out;
735 krb5_free_principal(context, creds->server);
736 creds->server = tmp_principal;
738 /* verify names */
739 if(flags & EXTRACT_TICKET_MATCH_REALM){
740 const char *srealm = krb5_principal_get_realm(context, creds->server);
741 const char *crealm = krb5_principal_get_realm(context, creds->client);
743 if (strcmp(rep->enc_part.srealm, srealm) != 0 ||
744 strcmp(rep->enc_part.srealm, crealm) != 0)
746 ret = KRB5KRB_AP_ERR_MODIFIED;
747 krb5_clear_error_message(context);
748 goto out;
752 /* compare nonces */
754 if (nonce != rep->enc_part.nonce) {
755 ret = KRB5KRB_AP_ERR_MODIFIED;
756 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
757 goto out;
760 /* set kdc-offset */
762 krb5_timeofday (context, &sec_now);
763 if (rep->enc_part.flags.initial
764 && context->kdc_sec_offset == 0
765 && krb5_config_get_bool (context, NULL,
766 "libdefaults",
767 "kdc_timesync",
768 NULL)) {
769 context->kdc_sec_offset = rep->enc_part.authtime - sec_now;
770 krb5_timeofday (context, &sec_now);
773 /* check all times */
775 if (rep->enc_part.starttime) {
776 tmp_time = *rep->enc_part.starttime;
777 } else
778 tmp_time = rep->enc_part.authtime;
780 if (creds->times.starttime == 0
781 && abs(tmp_time - sec_now) > context->max_skew) {
782 ret = KRB5KRB_AP_ERR_SKEW;
783 krb5_set_error_message (context, ret,
784 N_("time skew (%d) larger than max (%d)", ""),
785 abs(tmp_time - sec_now),
786 (int)context->max_skew);
787 goto out;
790 if (creds->times.starttime != 0
791 && tmp_time != creds->times.starttime) {
792 krb5_clear_error_message (context);
793 ret = KRB5KRB_AP_ERR_MODIFIED;
794 goto out;
797 creds->times.starttime = tmp_time;
799 if (rep->enc_part.renew_till) {
800 tmp_time = *rep->enc_part.renew_till;
801 } else
802 tmp_time = 0;
804 if (creds->times.renew_till != 0
805 && tmp_time > creds->times.renew_till) {
806 krb5_clear_error_message (context);
807 ret = KRB5KRB_AP_ERR_MODIFIED;
808 goto out;
811 creds->times.renew_till = tmp_time;
813 creds->times.authtime = rep->enc_part.authtime;
815 if (creds->times.endtime != 0
816 && rep->enc_part.endtime > creds->times.endtime) {
817 krb5_clear_error_message (context);
818 ret = KRB5KRB_AP_ERR_MODIFIED;
819 goto out;
822 creds->times.endtime = rep->enc_part.endtime;
824 if(rep->enc_part.caddr)
825 krb5_copy_addresses (context, rep->enc_part.caddr, &creds->addresses);
826 else if(addrs)
827 krb5_copy_addresses (context, addrs, &creds->addresses);
828 else {
829 creds->addresses.len = 0;
830 creds->addresses.val = NULL;
832 creds->flags.b = rep->enc_part.flags;
834 creds->authdata.len = 0;
835 creds->authdata.val = NULL;
837 /* extract ticket */
838 ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length,
839 &rep->kdc_rep.ticket, &len, ret);
840 if(ret)
841 goto out;
842 if (creds->ticket.length != len)
843 krb5_abortx(context, "internal error in ASN.1 encoder");
844 creds->second_ticket.length = 0;
845 creds->second_ticket.data = NULL;
848 out:
849 memset (rep->enc_part.key.keyvalue.data, 0,
850 rep->enc_part.key.keyvalue.length);
851 return ret;