etc/services - sync with NetBSD-8
[minix.git] / crypto / external / bsd / heimdal / dist / lib / krb5 / ticket.c
blob0a8c3e17a88d8584a1e186124d94258ada90a0b2
1 /* $NetBSD: ticket.c,v 1.1.1.2 2014/04/24 12:45:51 pettai Exp $ */
3 /*
4 * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * All rights reserved.
8 * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the Institute nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
38 #include "krb5_locl.h"
40 /**
41 * Free ticket and content
43 * @param context a Kerberos 5 context
44 * @param ticket ticket to free
46 * @return Returns 0 to indicate success. Otherwise an kerberos et
47 * error code is returned, see krb5_get_error_message().
49 * @ingroup krb5
52 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
53 krb5_free_ticket(krb5_context context,
54 krb5_ticket *ticket)
56 free_EncTicketPart(&ticket->ticket);
57 krb5_free_principal(context, ticket->client);
58 krb5_free_principal(context, ticket->server);
59 free(ticket);
60 return 0;
63 /**
64 * Copy ticket and content
66 * @param context a Kerberos 5 context
67 * @param from ticket to copy
68 * @param to new copy of ticket, free with krb5_free_ticket()
70 * @return Returns 0 to indicate success. Otherwise an kerberos et
71 * error code is returned, see krb5_get_error_message().
73 * @ingroup krb5
76 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
77 krb5_copy_ticket(krb5_context context,
78 const krb5_ticket *from,
79 krb5_ticket **to)
81 krb5_error_code ret;
82 krb5_ticket *tmp;
84 *to = NULL;
85 tmp = malloc(sizeof(*tmp));
86 if(tmp == NULL) {
87 krb5_set_error_message(context, ENOMEM,
88 N_("malloc: out of memory", ""));
89 return ENOMEM;
91 if((ret = copy_EncTicketPart(&from->ticket, &tmp->ticket))){
92 free(tmp);
93 return ret;
95 ret = krb5_copy_principal(context, from->client, &tmp->client);
96 if(ret){
97 free_EncTicketPart(&tmp->ticket);
98 free(tmp);
99 return ret;
101 ret = krb5_copy_principal(context, from->server, &tmp->server);
102 if(ret){
103 krb5_free_principal(context, tmp->client);
104 free_EncTicketPart(&tmp->ticket);
105 free(tmp);
106 return ret;
108 *to = tmp;
109 return 0;
113 * Return client principal in ticket
115 * @param context a Kerberos 5 context
116 * @param ticket ticket to copy
117 * @param client client principal, free with krb5_free_principal()
119 * @return Returns 0 to indicate success. Otherwise an kerberos et
120 * error code is returned, see krb5_get_error_message().
122 * @ingroup krb5
125 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
126 krb5_ticket_get_client(krb5_context context,
127 const krb5_ticket *ticket,
128 krb5_principal *client)
130 return krb5_copy_principal(context, ticket->client, client);
134 * Return server principal in ticket
136 * @param context a Kerberos 5 context
137 * @param ticket ticket to copy
138 * @param server server principal, free with krb5_free_principal()
140 * @return Returns 0 to indicate success. Otherwise an kerberos et
141 * error code is returned, see krb5_get_error_message().
143 * @ingroup krb5
146 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
147 krb5_ticket_get_server(krb5_context context,
148 const krb5_ticket *ticket,
149 krb5_principal *server)
151 return krb5_copy_principal(context, ticket->server, server);
155 * Return end time of ticket
157 * @param context a Kerberos 5 context
158 * @param ticket ticket to copy
160 * @return end time of ticket
162 * @ingroup krb5
165 KRB5_LIB_FUNCTION time_t KRB5_LIB_CALL
166 krb5_ticket_get_endtime(krb5_context context,
167 const krb5_ticket *ticket)
169 return ticket->ticket.endtime;
173 * Get the flags from the Kerberos ticket
175 * @param context Kerberos context
176 * @param ticket Kerberos ticket
178 * @return ticket flags
180 * @ingroup krb5_ticket
182 KRB5_LIB_FUNCTION unsigned long KRB5_LIB_CALL
183 krb5_ticket_get_flags(krb5_context context,
184 const krb5_ticket *ticket)
186 return TicketFlags2int(ticket->ticket.flags);
189 static int
190 find_type_in_ad(krb5_context context,
191 int type,
192 krb5_data *data,
193 krb5_boolean *found,
194 krb5_boolean failp,
195 krb5_keyblock *sessionkey,
196 const AuthorizationData *ad,
197 int level)
199 krb5_error_code ret = 0;
200 size_t i;
202 if (level > 9) {
203 ret = ENOENT; /* XXX */
204 krb5_set_error_message(context, ret,
205 N_("Authorization data nested deeper "
206 "then %d levels, stop searching", ""),
207 level);
208 goto out;
212 * Only copy out the element the first time we get to it, we need
213 * to run over the whole authorization data fields to check if
214 * there are any container clases we need to care about.
216 for (i = 0; i < ad->len; i++) {
217 if (!*found && ad->val[i].ad_type == type) {
218 ret = der_copy_octet_string(&ad->val[i].ad_data, data);
219 if (ret) {
220 krb5_set_error_message(context, ret,
221 N_("malloc: out of memory", ""));
222 goto out;
224 *found = TRUE;
225 continue;
227 switch (ad->val[i].ad_type) {
228 case KRB5_AUTHDATA_IF_RELEVANT: {
229 AuthorizationData child;
230 ret = decode_AuthorizationData(ad->val[i].ad_data.data,
231 ad->val[i].ad_data.length,
232 &child,
233 NULL);
234 if (ret) {
235 krb5_set_error_message(context, ret,
236 N_("Failed to decode "
237 "IF_RELEVANT with %d", ""),
238 (int)ret);
239 goto out;
241 ret = find_type_in_ad(context, type, data, found, FALSE,
242 sessionkey, &child, level + 1);
243 free_AuthorizationData(&child);
244 if (ret)
245 goto out;
246 break;
248 #if 0 /* XXX test */
249 case KRB5_AUTHDATA_KDC_ISSUED: {
250 AD_KDCIssued child;
252 ret = decode_AD_KDCIssued(ad->val[i].ad_data.data,
253 ad->val[i].ad_data.length,
254 &child,
255 NULL);
256 if (ret) {
257 krb5_set_error_message(context, ret,
258 N_("Failed to decode "
259 "AD_KDCIssued with %d", ""),
260 ret);
261 goto out;
263 if (failp) {
264 krb5_boolean valid;
265 krb5_data buf;
266 size_t len;
268 ASN1_MALLOC_ENCODE(AuthorizationData, buf.data, buf.length,
269 &child.elements, &len, ret);
270 if (ret) {
271 free_AD_KDCIssued(&child);
272 krb5_clear_error_message(context);
273 goto out;
275 if(buf.length != len)
276 krb5_abortx(context, "internal error in ASN.1 encoder");
278 ret = krb5_c_verify_checksum(context, sessionkey, 19, &buf,
279 &child.ad_checksum, &valid);
280 krb5_data_free(&buf);
281 if (ret) {
282 free_AD_KDCIssued(&child);
283 goto out;
285 if (!valid) {
286 krb5_clear_error_message(context);
287 ret = ENOENT;
288 free_AD_KDCIssued(&child);
289 goto out;
292 ret = find_type_in_ad(context, type, data, found, failp, sessionkey,
293 &child.elements, level + 1);
294 free_AD_KDCIssued(&child);
295 if (ret)
296 goto out;
297 break;
299 #endif
300 case KRB5_AUTHDATA_AND_OR:
301 if (!failp)
302 break;
303 ret = ENOENT; /* XXX */
304 krb5_set_error_message(context, ret,
305 N_("Authorization data contains "
306 "AND-OR element that is unknown to the "
307 "application", ""));
308 goto out;
309 default:
310 if (!failp)
311 break;
312 ret = ENOENT; /* XXX */
313 krb5_set_error_message(context, ret,
314 N_("Authorization data contains "
315 "unknown type (%d) ", ""),
316 ad->val[i].ad_type);
317 goto out;
320 out:
321 if (ret) {
322 if (*found) {
323 krb5_data_free(data);
324 *found = 0;
327 return ret;
331 * Extract the authorization data type of type from the ticket. Store
332 * the field in data. This function is to use for kerberos
333 * applications.
335 * @param context a Kerberos 5 context
336 * @param ticket Kerberos ticket
337 * @param type type to fetch
338 * @param data returned data, free with krb5_data_free()
340 * @ingroup krb5
343 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
344 krb5_ticket_get_authorization_data_type(krb5_context context,
345 krb5_ticket *ticket,
346 int type,
347 krb5_data *data)
349 AuthorizationData *ad;
350 krb5_error_code ret;
351 krb5_boolean found = FALSE;
353 krb5_data_zero(data);
355 ad = ticket->ticket.authorization_data;
356 if (ticket->ticket.authorization_data == NULL) {
357 krb5_set_error_message(context, ENOENT,
358 N_("Ticket have not authorization data", ""));
359 return ENOENT; /* XXX */
362 ret = find_type_in_ad(context, type, data, &found, TRUE,
363 &ticket->ticket.key, ad, 0);
364 if (ret)
365 return ret;
366 if (!found) {
367 krb5_set_error_message(context, ENOENT,
368 N_("Ticket have not "
369 "authorization data of type %d", ""),
370 type);
371 return ENOENT; /* XXX */
373 return 0;
376 static krb5_error_code
377 check_server_referral(krb5_context context,
378 krb5_kdc_rep *rep,
379 unsigned flags,
380 krb5_const_principal requested,
381 krb5_const_principal returned,
382 krb5_keyblock * key)
384 krb5_error_code ret;
385 PA_ServerReferralData ref;
386 krb5_crypto session;
387 EncryptedData ed;
388 size_t len;
389 krb5_data data;
390 PA_DATA *pa;
391 int i = 0, cmp;
393 if (rep->kdc_rep.padata == NULL)
394 goto noreferral;
396 pa = krb5_find_padata(rep->kdc_rep.padata->val,
397 rep->kdc_rep.padata->len,
398 KRB5_PADATA_SERVER_REFERRAL, &i);
399 if (pa == NULL)
400 goto noreferral;
402 memset(&ed, 0, sizeof(ed));
403 memset(&ref, 0, sizeof(ref));
405 ret = decode_EncryptedData(pa->padata_value.data,
406 pa->padata_value.length,
407 &ed, &len);
408 if (ret)
409 return ret;
410 if (len != pa->padata_value.length) {
411 free_EncryptedData(&ed);
412 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
413 N_("Referral EncryptedData wrong for realm %s",
414 "realm"), requested->realm);
415 return KRB5KRB_AP_ERR_MODIFIED;
418 ret = krb5_crypto_init(context, key, 0, &session);
419 if (ret) {
420 free_EncryptedData(&ed);
421 return ret;
424 ret = krb5_decrypt_EncryptedData(context, session,
425 KRB5_KU_PA_SERVER_REFERRAL,
426 &ed, &data);
427 free_EncryptedData(&ed);
428 krb5_crypto_destroy(context, session);
429 if (ret)
430 return ret;
432 ret = decode_PA_ServerReferralData(data.data, data.length, &ref, &len);
433 if (ret) {
434 krb5_data_free(&data);
435 return ret;
437 krb5_data_free(&data);
439 if (strcmp(requested->realm, returned->realm) != 0) {
440 free_PA_ServerReferralData(&ref);
441 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
442 N_("server ref realm mismatch, "
443 "requested realm %s got back %s", ""),
444 requested->realm, returned->realm);
445 return KRB5KRB_AP_ERR_MODIFIED;
448 if (krb5_principal_is_krbtgt(context, returned)) {
449 const char *realm = returned->name.name_string.val[1];
451 if (ref.referred_realm == NULL
452 || strcmp(*ref.referred_realm, realm) != 0)
454 free_PA_ServerReferralData(&ref);
455 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
456 N_("tgt returned with wrong ref", ""));
457 return KRB5KRB_AP_ERR_MODIFIED;
459 } else if (krb5_principal_compare(context, returned, requested) == 0) {
460 free_PA_ServerReferralData(&ref);
461 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
462 N_("req princ no same as returned", ""));
463 return KRB5KRB_AP_ERR_MODIFIED;
466 if (ref.requested_principal_name) {
467 cmp = _krb5_principal_compare_PrincipalName(context,
468 requested,
469 ref.requested_principal_name);
470 if (!cmp) {
471 free_PA_ServerReferralData(&ref);
472 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
473 N_("referred principal not same "
474 "as requested", ""));
475 return KRB5KRB_AP_ERR_MODIFIED;
477 } else if (flags & EXTRACT_TICKET_AS_REQ) {
478 free_PA_ServerReferralData(&ref);
479 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
480 N_("Requested principal missing on AS-REQ", ""));
481 return KRB5KRB_AP_ERR_MODIFIED;
484 free_PA_ServerReferralData(&ref);
486 return ret;
487 noreferral:
489 * Expect excact match or that we got a krbtgt
491 if (krb5_principal_compare(context, requested, returned) != TRUE &&
492 (krb5_realm_compare(context, requested, returned) != TRUE &&
493 krb5_principal_is_krbtgt(context, returned) != TRUE))
495 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
496 N_("Not same server principal returned "
497 "as requested", ""));
498 return KRB5KRB_AP_ERR_MODIFIED;
500 return 0;
505 * Verify referral data
509 static krb5_error_code
510 check_client_referral(krb5_context context,
511 krb5_kdc_rep *rep,
512 krb5_const_principal requested,
513 krb5_const_principal mapped,
514 krb5_keyblock const * key)
516 krb5_error_code ret;
517 PA_ClientCanonicalized canon;
518 krb5_crypto crypto;
519 krb5_data data;
520 PA_DATA *pa;
521 size_t len;
522 int i = 0;
524 if (rep->kdc_rep.padata == NULL)
525 goto noreferral;
527 pa = krb5_find_padata(rep->kdc_rep.padata->val,
528 rep->kdc_rep.padata->len,
529 KRB5_PADATA_CLIENT_CANONICALIZED, &i);
530 if (pa == NULL)
531 goto noreferral;
533 ret = decode_PA_ClientCanonicalized(pa->padata_value.data,
534 pa->padata_value.length,
535 &canon, &len);
536 if (ret) {
537 krb5_set_error_message(context, ret,
538 N_("Failed to decode ClientCanonicalized "
539 "from realm %s", ""), requested->realm);
540 return ret;
543 ASN1_MALLOC_ENCODE(PA_ClientCanonicalizedNames, data.data, data.length,
544 &canon.names, &len, ret);
545 if (ret) {
546 free_PA_ClientCanonicalized(&canon);
547 return ret;
549 if (data.length != len)
550 krb5_abortx(context, "internal asn.1 error");
552 ret = krb5_crypto_init(context, key, 0, &crypto);
553 if (ret) {
554 free(data.data);
555 free_PA_ClientCanonicalized(&canon);
556 return ret;
559 ret = krb5_verify_checksum(context, crypto, KRB5_KU_CANONICALIZED_NAMES,
560 data.data, data.length,
561 &canon.canon_checksum);
562 krb5_crypto_destroy(context, crypto);
563 free(data.data);
564 if (ret) {
565 krb5_set_error_message(context, ret,
566 N_("Failed to verify client canonicalized "
567 "data from realm %s", ""),
568 requested->realm);
569 free_PA_ClientCanonicalized(&canon);
570 return ret;
573 if (!_krb5_principal_compare_PrincipalName(context,
574 requested,
575 &canon.names.requested_name))
577 free_PA_ClientCanonicalized(&canon);
578 krb5_set_error_message(context, KRB5_PRINC_NOMATCH,
579 N_("Requested name doesn't match"
580 " in client referral", ""));
581 return KRB5_PRINC_NOMATCH;
583 if (!_krb5_principal_compare_PrincipalName(context,
584 mapped,
585 &canon.names.mapped_name))
587 free_PA_ClientCanonicalized(&canon);
588 krb5_set_error_message(context, KRB5_PRINC_NOMATCH,
589 N_("Mapped name doesn't match"
590 " in client referral", ""));
591 return KRB5_PRINC_NOMATCH;
594 return 0;
596 noreferral:
597 if (krb5_principal_compare(context, requested, mapped) == FALSE) {
598 krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
599 N_("Not same client principal returned "
600 "as requested", ""));
601 return KRB5KRB_AP_ERR_MODIFIED;
603 return 0;
607 static krb5_error_code KRB5_CALLCONV
608 decrypt_tkt (krb5_context context,
609 krb5_keyblock *key,
610 krb5_key_usage usage,
611 krb5_const_pointer decrypt_arg,
612 krb5_kdc_rep *dec_rep)
614 krb5_error_code ret;
615 krb5_data data;
616 size_t size;
617 krb5_crypto crypto;
619 ret = krb5_crypto_init(context, key, 0, &crypto);
620 if (ret)
621 return ret;
623 ret = krb5_decrypt_EncryptedData (context,
624 crypto,
625 usage,
626 &dec_rep->kdc_rep.enc_part,
627 &data);
628 krb5_crypto_destroy(context, crypto);
630 if (ret)
631 return ret;
633 ret = decode_EncASRepPart(data.data,
634 data.length,
635 &dec_rep->enc_part,
636 &size);
637 if (ret)
638 ret = decode_EncTGSRepPart(data.data,
639 data.length,
640 &dec_rep->enc_part,
641 &size);
642 krb5_data_free (&data);
643 if (ret) {
644 krb5_set_error_message(context, ret,
645 N_("Failed to decode encpart in ticket", ""));
646 return ret;
648 return 0;
652 _krb5_extract_ticket(krb5_context context,
653 krb5_kdc_rep *rep,
654 krb5_creds *creds,
655 krb5_keyblock *key,
656 krb5_const_pointer keyseed,
657 krb5_key_usage key_usage,
658 krb5_addresses *addrs,
659 unsigned nonce,
660 unsigned flags,
661 krb5_decrypt_proc decrypt_proc,
662 krb5_const_pointer decryptarg)
664 krb5_error_code ret;
665 krb5_principal tmp_principal;
666 size_t len = 0;
667 time_t tmp_time;
668 krb5_timestamp sec_now;
670 /* decrypt */
672 if (decrypt_proc == NULL)
673 decrypt_proc = decrypt_tkt;
675 ret = (*decrypt_proc)(context, key, key_usage, decryptarg, rep);
676 if (ret)
677 goto out;
679 /* save session key */
681 creds->session.keyvalue.length = 0;
682 creds->session.keyvalue.data = NULL;
683 creds->session.keytype = rep->enc_part.key.keytype;
684 ret = krb5_data_copy (&creds->session.keyvalue,
685 rep->enc_part.key.keyvalue.data,
686 rep->enc_part.key.keyvalue.length);
687 if (ret) {
688 krb5_clear_error_message(context);
689 goto out;
692 /* compare client and save */
693 ret = _krb5_principalname2krb5_principal (context,
694 &tmp_principal,
695 rep->kdc_rep.cname,
696 rep->kdc_rep.crealm);
697 if (ret)
698 goto out;
700 /* check client referral and save principal */
701 /* anonymous here ? */
702 if((flags & EXTRACT_TICKET_ALLOW_CNAME_MISMATCH) == 0) {
703 ret = check_client_referral(context, rep,
704 creds->client,
705 tmp_principal,
706 &creds->session);
707 if (ret) {
708 krb5_free_principal (context, tmp_principal);
709 goto out;
712 krb5_free_principal (context, creds->client);
713 creds->client = tmp_principal;
715 /* check server referral and save principal */
716 ret = _krb5_principalname2krb5_principal (context,
717 &tmp_principal,
718 rep->kdc_rep.ticket.sname,
719 rep->kdc_rep.ticket.realm);
720 if (ret)
721 goto out;
722 if((flags & EXTRACT_TICKET_ALLOW_SERVER_MISMATCH) == 0){
723 ret = check_server_referral(context,
724 rep,
725 flags,
726 creds->server,
727 tmp_principal,
728 &creds->session);
729 if (ret) {
730 krb5_free_principal (context, tmp_principal);
731 goto out;
734 krb5_free_principal(context, creds->server);
735 creds->server = tmp_principal;
737 /* verify names */
738 if(flags & EXTRACT_TICKET_MATCH_REALM){
739 const char *srealm = krb5_principal_get_realm(context, creds->server);
740 const char *crealm = krb5_principal_get_realm(context, creds->client);
742 if (strcmp(rep->enc_part.srealm, srealm) != 0 ||
743 strcmp(rep->enc_part.srealm, crealm) != 0)
745 ret = KRB5KRB_AP_ERR_MODIFIED;
746 krb5_clear_error_message(context);
747 goto out;
751 /* compare nonces */
753 if (nonce != (unsigned)rep->enc_part.nonce) {
754 ret = KRB5KRB_AP_ERR_MODIFIED;
755 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
756 goto out;
759 /* set kdc-offset */
761 krb5_timeofday (context, &sec_now);
762 if (rep->enc_part.flags.initial
763 && (flags & EXTRACT_TICKET_TIMESYNC)
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;