2 * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
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
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
36 #include "krb5_locl.h"
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().
50 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
51 krb5_free_ticket(krb5_context context
,
54 free_EncTicketPart(&ticket
->ticket
);
55 krb5_free_principal(context
, ticket
->client
);
56 krb5_free_principal(context
, ticket
->server
);
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().
74 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
75 krb5_copy_ticket(krb5_context context
,
76 const krb5_ticket
*from
,
83 tmp
= malloc(sizeof(*tmp
));
85 return krb5_enomem(context
);
86 if((ret
= copy_EncTicketPart(&from
->ticket
, &tmp
->ticket
))){
90 ret
= krb5_copy_principal(context
, from
->client
, &tmp
->client
);
92 free_EncTicketPart(&tmp
->ticket
);
96 ret
= krb5_copy_principal(context
, from
->server
, &tmp
->server
);
98 krb5_free_principal(context
, tmp
->client
);
99 free_EncTicketPart(&tmp
->ticket
);
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().
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().
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 a ticket
152 * @param context a Kerberos 5 context
153 * @param ticket ticket to copy
155 * @return end time of ticket
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 * Return authentication, start, end, and renew limit times of a ticket
170 * @param context a Kerberos 5 context
171 * @param ticket ticket to copy
172 * @param t pointer to krb5_times structure
177 KRB5_LIB_FUNCTION
void KRB5_LIB_CALL
178 krb5_ticket_get_times(krb5_context context
,
179 const krb5_ticket
*ticket
,
182 t
->authtime
= ticket
->ticket
.authtime
;
183 t
->starttime
= ticket
->ticket
.starttime
? *ticket
->ticket
.starttime
:
185 t
->endtime
= ticket
->ticket
.endtime
;
186 t
->renew_till
= ticket
->ticket
.renew_till
? *ticket
->ticket
.renew_till
:
191 * Get the flags from the Kerberos ticket
193 * @param context Kerberos context
194 * @param ticket Kerberos ticket
196 * @return ticket flags
198 * @ingroup krb5_ticket
200 KRB5_LIB_FUNCTION
unsigned long KRB5_LIB_CALL
201 krb5_ticket_get_flags(krb5_context context
,
202 const krb5_ticket
*ticket
)
204 return TicketFlags2int(ticket
->ticket
.flags
);
208 find_type_in_ad(krb5_context context
,
213 krb5_keyblock
*sessionkey
,
214 const AuthorizationData
*ad
,
217 krb5_error_code ret
= 0;
221 ret
= ENOENT
; /* XXX */
222 krb5_set_error_message(context
, ret
,
223 N_("Authorization data nested deeper "
224 "then %d levels, stop searching", ""),
230 * Only copy out the element the first time we get to it, we need
231 * to run over the whole authorization data fields to check if
232 * there are any container clases we need to care about.
234 for (i
= 0; i
< ad
->len
; i
++) {
235 if (!*found
&& ad
->val
[i
].ad_type
== type
) {
236 ret
= der_copy_octet_string(&ad
->val
[i
].ad_data
, data
);
238 krb5_set_error_message(context
, ret
,
239 N_("malloc: out of memory", ""));
245 switch (ad
->val
[i
].ad_type
) {
246 case KRB5_AUTHDATA_IF_RELEVANT
: {
247 AuthorizationData child
;
248 ret
= decode_AuthorizationData(ad
->val
[i
].ad_data
.data
,
249 ad
->val
[i
].ad_data
.length
,
253 krb5_set_error_message(context
, ret
,
254 N_("Failed to decode "
255 "IF_RELEVANT with %d", ""),
259 ret
= find_type_in_ad(context
, type
, data
, found
, FALSE
,
260 sessionkey
, &child
, level
+ 1);
261 free_AuthorizationData(&child
);
267 case KRB5_AUTHDATA_KDC_ISSUED
: {
270 ret
= decode_AD_KDCIssued(ad
->val
[i
].ad_data
.data
,
271 ad
->val
[i
].ad_data
.length
,
275 krb5_set_error_message(context
, ret
,
276 N_("Failed to decode "
277 "AD_KDCIssued with %d", ""),
286 ASN1_MALLOC_ENCODE(AuthorizationData
, buf
.data
, buf
.length
,
287 &child
.elements
, &len
, ret
);
289 free_AD_KDCIssued(&child
);
290 krb5_clear_error_message(context
);
293 if(buf
.length
!= len
)
294 krb5_abortx(context
, "internal error in ASN.1 encoder");
296 ret
= krb5_c_verify_checksum(context
, sessionkey
, 19, &buf
,
297 &child
.ad_checksum
, &valid
);
298 krb5_data_free(&buf
);
300 free_AD_KDCIssued(&child
);
304 krb5_clear_error_message(context
);
306 free_AD_KDCIssued(&child
);
310 ret
= find_type_in_ad(context
, type
, data
, found
, failp
, sessionkey
,
311 &child
.elements
, level
+ 1);
312 free_AD_KDCIssued(&child
);
318 case KRB5_AUTHDATA_AND_OR
:
321 ret
= ENOENT
; /* XXX */
322 krb5_set_error_message(context
, ret
,
323 N_("Authorization data contains "
324 "AND-OR element that is unknown to the "
330 ret
= ENOENT
; /* XXX */
331 krb5_set_error_message(context
, ret
,
332 N_("Authorization data contains "
333 "unknown type (%d) ", ""),
341 krb5_data_free(data
);
348 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
349 _krb5_get_ad(krb5_context context
,
350 const AuthorizationData
*ad
,
351 krb5_keyblock
*sessionkey
,
355 krb5_boolean found
= FALSE
;
358 krb5_data_zero(data
);
361 krb5_set_error_message(context
, ENOENT
,
362 N_("No authorization data", ""));
363 return ENOENT
; /* XXX */
366 ret
= find_type_in_ad(context
, type
, data
, &found
, TRUE
, sessionkey
, ad
, 0);
370 krb5_set_error_message(context
, ENOENT
,
371 N_("Have no authorization data of type %d", ""),
373 return ENOENT
; /* XXX */
380 * Extract the authorization data type of type from the ticket. Store
381 * the field in data. This function is to use for kerberos
384 * @param context a Kerberos 5 context
385 * @param ticket Kerberos ticket
386 * @param type type to fetch
387 * @param data returned data, free with krb5_data_free()
392 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
393 krb5_ticket_get_authorization_data_type(krb5_context context
,
398 AuthorizationData
*ad
;
400 krb5_boolean found
= FALSE
;
402 krb5_data_zero(data
);
404 ad
= ticket
->ticket
.authorization_data
;
405 if (ticket
->ticket
.authorization_data
== NULL
) {
406 krb5_set_error_message(context
, ENOENT
,
407 N_("Ticket has no authorization data", ""));
408 return ENOENT
; /* XXX */
411 ret
= find_type_in_ad(context
, type
, data
, &found
, TRUE
,
412 &ticket
->ticket
.key
, ad
, 0);
416 krb5_set_error_message(context
, ENOENT
,
418 "authorization data of type %d", ""),
420 return ENOENT
; /* XXX */
425 static krb5_error_code
426 check_server_referral(krb5_context context
,
429 krb5_const_principal requested
,
430 krb5_const_principal returned
,
434 PA_ServerReferralData ref
;
442 if (rep
->kdc_rep
.padata
== NULL
)
445 pa
= krb5_find_padata(rep
->kdc_rep
.padata
->val
,
446 rep
->kdc_rep
.padata
->len
,
447 KRB5_PADATA_SERVER_REFERRAL
, &i
);
451 memset(&ed
, 0, sizeof(ed
));
452 memset(&ref
, 0, sizeof(ref
));
454 ret
= decode_EncryptedData(pa
->padata_value
.data
,
455 pa
->padata_value
.length
,
459 if (len
!= pa
->padata_value
.length
) {
460 free_EncryptedData(&ed
);
461 krb5_set_error_message(context
, KRB5KRB_AP_ERR_MODIFIED
,
462 N_("Referral EncryptedData wrong for realm %s",
463 "realm"), requested
->realm
);
464 return KRB5KRB_AP_ERR_MODIFIED
;
467 ret
= krb5_crypto_init(context
, key
, 0, &session
);
469 free_EncryptedData(&ed
);
473 ret
= krb5_decrypt_EncryptedData(context
, session
,
474 KRB5_KU_PA_SERVER_REFERRAL
,
476 free_EncryptedData(&ed
);
477 krb5_crypto_destroy(context
, session
);
481 ret
= decode_PA_ServerReferralData(data
.data
, data
.length
, &ref
, &len
);
483 krb5_data_free(&data
);
486 krb5_data_free(&data
);
488 if (strcmp(requested
->realm
, returned
->realm
) != 0) {
489 free_PA_ServerReferralData(&ref
);
490 krb5_set_error_message(context
, KRB5KRB_AP_ERR_MODIFIED
,
491 N_("server ref realm mismatch, "
492 "requested realm %s got back %s", ""),
493 requested
->realm
, returned
->realm
);
494 return KRB5KRB_AP_ERR_MODIFIED
;
497 if (krb5_principal_is_krbtgt(context
, returned
)) {
498 const char *realm
= returned
->name
.name_string
.val
[1];
500 if (ref
.referred_realm
== NULL
501 || strcmp(*ref
.referred_realm
, realm
) != 0)
503 free_PA_ServerReferralData(&ref
);
504 krb5_set_error_message(context
, KRB5KRB_AP_ERR_MODIFIED
,
505 N_("tgt returned with wrong ref", ""));
506 return KRB5KRB_AP_ERR_MODIFIED
;
508 } else if (krb5_principal_compare(context
, returned
, requested
) == 0) {
509 free_PA_ServerReferralData(&ref
);
510 krb5_set_error_message(context
, KRB5KRB_AP_ERR_MODIFIED
,
511 N_("req princ no same as returned", ""));
512 return KRB5KRB_AP_ERR_MODIFIED
;
515 if (ref
.requested_principal_name
) {
516 cmp
= _krb5_principal_compare_PrincipalName(context
,
518 ref
.requested_principal_name
);
520 free_PA_ServerReferralData(&ref
);
521 krb5_set_error_message(context
, KRB5KRB_AP_ERR_MODIFIED
,
522 N_("referred principal not same "
523 "as requested", ""));
524 return KRB5KRB_AP_ERR_MODIFIED
;
526 } else if (flags
& EXTRACT_TICKET_AS_REQ
) {
527 free_PA_ServerReferralData(&ref
);
528 krb5_set_error_message(context
, KRB5KRB_AP_ERR_MODIFIED
,
529 N_("Requested principal missing on AS-REQ", ""));
530 return KRB5KRB_AP_ERR_MODIFIED
;
533 free_PA_ServerReferralData(&ref
);
538 * Expect excact match or that we got a krbtgt
540 if (krb5_principal_compare(context
, requested
, returned
) != TRUE
&&
541 (krb5_realm_compare(context
, requested
, returned
) != TRUE
&&
542 krb5_principal_is_krbtgt(context
, returned
) != TRUE
))
544 krb5_set_error_message(context
, KRB5KRB_AP_ERR_MODIFIED
,
545 N_("Not same server principal returned "
546 "as requested", ""));
547 return KRB5KRB_AP_ERR_MODIFIED
;
553 * Verify KDC supported anonymous if requested
555 static krb5_error_code
556 check_client_anonymous(krb5_context context
,
558 krb5_const_principal requested
,
559 krb5_const_principal mapped
,
560 krb5_boolean is_tgs_rep
)
564 if (!rep
->enc_part
.flags
.anonymous
)
565 return KRB5KDC_ERR_BADOPTION
;
568 * Here we must validate that the AS returned a ticket of the expected type
569 * for either a fully anonymous request, or authenticated request for an
570 * anonymous ticket. If this is a TGS request, we're done. Then if the
571 * 'requested' principal was anonymous, we'll check the 'mapped' principal
572 * accordingly (without enforcing the name type and perhaps the realm).
573 * Finally, if the 'requested' principal was not anonymous, well check
574 * that the 'mapped' principal has an anonymous name and type, in a
575 * non-anonymous realm. (Should we also be checking for a realm match
576 * between the request and the mapped name in this case?)
579 flags
= KRB5_ANON_MATCH_ANY_NONT
;
580 else if (krb5_principal_is_anonymous(context
, requested
,
581 KRB5_ANON_MATCH_ANY_NONT
))
582 flags
= KRB5_ANON_MATCH_UNAUTHENTICATED
| KRB5_ANON_IGNORE_NAME_TYPE
;
584 flags
= KRB5_ANON_MATCH_AUTHENTICATED
;
586 if (!krb5_principal_is_anonymous(context
, mapped
, flags
))
587 return KRB5KRB_AP_ERR_MODIFIED
;
593 * Verify returned client principal name in anonymous/referral case
596 static krb5_error_code
597 check_client_mismatch(krb5_context context
,
599 krb5_const_principal requested
,
600 krb5_const_principal mapped
,
601 krb5_keyblock
const * key
)
603 if (rep
->enc_part
.flags
.anonymous
) {
604 if (!krb5_principal_is_anonymous(context
, mapped
,
605 KRB5_ANON_MATCH_ANY_NONT
)) {
606 krb5_set_error_message(context
, KRB5KRB_AP_ERR_MODIFIED
,
607 N_("Anonymous ticket does not contain anonymous "
609 return KRB5KRB_AP_ERR_MODIFIED
;
612 if (krb5_principal_compare(context
, requested
, mapped
) == FALSE
&&
613 !rep
->enc_part
.flags
.enc_pa_rep
) {
614 krb5_set_error_message(context
, KRB5KRB_AP_ERR_MODIFIED
,
615 N_("Not same client principal returned "
616 "as requested", ""));
617 return KRB5KRB_AP_ERR_MODIFIED
;
625 static krb5_error_code KRB5_CALLCONV
626 decrypt_tkt (krb5_context context
,
628 krb5_key_usage usage
,
629 krb5_const_pointer decrypt_arg
,
630 krb5_kdc_rep
*dec_rep
)
637 ret
= krb5_crypto_init(context
, key
, 0, &crypto
);
641 ret
= krb5_decrypt_EncryptedData (context
,
644 &dec_rep
->kdc_rep
.enc_part
,
646 krb5_crypto_destroy(context
, crypto
);
651 ret
= decode_EncASRepPart(data
.data
,
656 ret
= decode_EncTGSRepPart(data
.data
,
660 krb5_data_free (&data
);
662 krb5_set_error_message(context
, ret
,
663 N_("Failed to decode encpart in ticket", ""));
669 KRB5_LIB_FUNCTION
int KRB5_LIB_CALL
670 _krb5_extract_ticket(krb5_context context
,
674 krb5_const_pointer keyseed
,
675 krb5_key_usage key_usage
,
676 krb5_addresses
*addrs
,
680 krb5_decrypt_proc decrypt_proc
,
681 krb5_const_pointer decryptarg
)
684 krb5_principal tmp_principal
;
687 krb5_timestamp sec_now
;
691 if (decrypt_proc
== NULL
)
692 decrypt_proc
= decrypt_tkt
;
694 ret
= (*decrypt_proc
)(context
, key
, key_usage
, decryptarg
, rep
);
698 if (rep
->enc_part
.flags
.enc_pa_rep
&& request
) {
699 krb5_crypto crypto
= NULL
;
704 _krb5_debug(context
, 5, "processing enc-ap-rep");
706 if (rep
->enc_part
.encrypted_pa_data
== NULL
||
707 (pa
= krb5_find_padata(rep
->enc_part
.encrypted_pa_data
->val
,
708 rep
->enc_part
.encrypted_pa_data
->len
,
709 KRB5_PADATA_REQ_ENC_PA_REP
,
712 _krb5_debug(context
, 5, "KRB5_PADATA_REQ_ENC_PA_REP missing");
713 ret
= KRB5KRB_AP_ERR_MODIFIED
;
717 ret
= krb5_crypto_init(context
, key
, 0, &crypto
);
721 ret
= decode_Checksum(pa
->padata_value
.data
,
722 pa
->padata_value
.length
,
725 krb5_crypto_destroy(context
, crypto
);
729 ret
= krb5_verify_checksum(context
, crypto
,
731 request
->data
, request
->length
,
733 krb5_crypto_destroy(context
, crypto
);
734 free_Checksum(&cksum
);
735 _krb5_debug(context
, 5, "enc-ap-rep: %svalid", (ret
== 0) ? "" : "in");
740 /* save session key */
742 creds
->session
.keyvalue
.length
= 0;
743 creds
->session
.keyvalue
.data
= NULL
;
744 creds
->session
.keytype
= rep
->enc_part
.key
.keytype
;
745 ret
= krb5_data_copy (&creds
->session
.keyvalue
,
746 rep
->enc_part
.key
.keyvalue
.data
,
747 rep
->enc_part
.key
.keyvalue
.length
);
749 krb5_clear_error_message(context
);
753 /* compare client and save */
754 ret
= _krb5_principalname2krb5_principal(context
,
757 rep
->kdc_rep
.crealm
);
761 /* check KDC supported anonymous if it was requested */
762 if (flags
& EXTRACT_TICKET_MATCH_ANON
) {
763 ret
= check_client_anonymous(context
,rep
,
766 request
== NULL
); /* is TGS */
768 krb5_free_principal(context
, tmp_principal
);
773 /* check client referral and save principal */
774 if((flags
& EXTRACT_TICKET_ALLOW_CNAME_MISMATCH
) == 0) {
775 ret
= check_client_mismatch(context
, rep
,
780 krb5_free_principal (context
, tmp_principal
);
784 krb5_free_principal (context
, creds
->client
);
785 creds
->client
= tmp_principal
;
787 /* check server referral and save principal */
788 ret
= _krb5_principalname2krb5_principal (context
,
791 rep
->enc_part
.srealm
);
794 if((flags
& EXTRACT_TICKET_ALLOW_SERVER_MISMATCH
) == 0){
795 ret
= check_server_referral(context
,
802 krb5_free_principal (context
, tmp_principal
);
806 krb5_free_principal(context
, creds
->server
);
807 creds
->server
= tmp_principal
;
810 if(flags
& EXTRACT_TICKET_MATCH_REALM
){
811 const char *srealm
= krb5_principal_get_realm(context
, creds
->server
);
812 const char *crealm
= krb5_principal_get_realm(context
, creds
->client
);
814 if (strcmp(rep
->enc_part
.srealm
, srealm
) != 0 ||
815 strcmp(rep
->enc_part
.srealm
, crealm
) != 0)
817 ret
= KRB5KRB_AP_ERR_MODIFIED
;
818 krb5_clear_error_message(context
);
825 if (nonce
!= (unsigned)rep
->enc_part
.nonce
) {
826 ret
= KRB5KRB_AP_ERR_MODIFIED
;
827 krb5_set_error_message(context
, ret
, N_("malloc: out of memory", ""));
833 krb5_timeofday (context
, &sec_now
);
834 if (rep
->enc_part
.flags
.initial
835 && (flags
& EXTRACT_TICKET_TIMESYNC
)
836 && context
->kdc_sec_offset
== 0
837 && krb5_config_get_bool (context
, NULL
,
841 context
->kdc_sec_offset
= rep
->enc_part
.authtime
- sec_now
;
842 krb5_timeofday (context
, &sec_now
);
845 /* check all times */
847 if (rep
->enc_part
.starttime
) {
848 tmp_time
= *rep
->enc_part
.starttime
;
850 tmp_time
= rep
->enc_part
.authtime
;
852 if (creds
->times
.starttime
== 0
853 && krb5_time_abs(tmp_time
, sec_now
) > context
->max_skew
) {
854 ret
= KRB5KRB_AP_ERR_SKEW
;
855 krb5_set_error_message (context
, ret
,
856 N_("time skew (%ld) larger than max (%ld)", ""),
857 krb5_time_abs(tmp_time
, sec_now
),
858 (long)context
->max_skew
);
862 if (creds
->times
.starttime
!= 0
863 && tmp_time
!= creds
->times
.starttime
) {
864 krb5_clear_error_message (context
);
865 ret
= KRB5KRB_AP_ERR_MODIFIED
;
869 creds
->times
.starttime
= tmp_time
;
871 if (rep
->enc_part
.renew_till
) {
872 tmp_time
= *rep
->enc_part
.renew_till
;
876 if (creds
->times
.renew_till
!= 0
877 && tmp_time
> creds
->times
.renew_till
) {
878 krb5_clear_error_message (context
);
879 ret
= KRB5KRB_AP_ERR_MODIFIED
;
883 creds
->times
.renew_till
= tmp_time
;
885 creds
->times
.authtime
= rep
->enc_part
.authtime
;
887 if (creds
->times
.endtime
!= 0
888 && rep
->enc_part
.endtime
> creds
->times
.endtime
) {
889 krb5_clear_error_message (context
);
890 ret
= KRB5KRB_AP_ERR_MODIFIED
;
894 creds
->times
.endtime
= rep
->enc_part
.endtime
;
896 if(rep
->enc_part
.caddr
)
897 krb5_copy_addresses (context
, rep
->enc_part
.caddr
, &creds
->addresses
);
899 krb5_copy_addresses (context
, addrs
, &creds
->addresses
);
901 creds
->addresses
.len
= 0;
902 creds
->addresses
.val
= NULL
;
904 creds
->flags
.b
= rep
->enc_part
.flags
;
906 creds
->authdata
.len
= 0;
907 creds
->authdata
.val
= NULL
;
910 ASN1_MALLOC_ENCODE(Ticket
, creds
->ticket
.data
, creds
->ticket
.length
,
911 &rep
->kdc_rep
.ticket
, &len
, ret
);
914 if (creds
->ticket
.length
!= len
)
915 krb5_abortx(context
, "internal error in ASN.1 encoder");
916 creds
->second_ticket
.length
= 0;
917 creds
->second_ticket
.data
= NULL
;
921 memset (rep
->enc_part
.key
.keyvalue
.data
, 0,
922 rep
->enc_part
.key
.keyvalue
.length
);