2 * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
36 __RCSID("$Heimdal: krb5tgs.c 22071 2007-11-14 20:04:50Z lha $"
37 "$NetBSD: krb5tgs.c,v 1.1 2008/03/22 08:37:03 mlelstv Exp $");
40 * return the realm of a krbtgt-ticket or NULL
44 get_krbtgt_realm(const PrincipalName
*p
)
46 if(p
->name_string
.len
== 2
47 && strcmp(p
->name_string
.val
[0], KRB5_TGS_NAME
) == 0)
48 return p
->name_string
.val
[1];
54 * The KDC might add a signed path to the ticket authorization data
55 * field. This is to avoid server impersonating clients and the
56 * request constrained delegation.
58 * This is done by storing a KRB5_AUTHDATA_IF_RELEVANT with a single
59 * entry of type KRB5SignedPath.
62 static krb5_error_code
63 find_KRB5SignedPath(krb5_context context
,
64 const AuthorizationData
*ad
,
67 AuthorizationData child
;
71 if (ad
== NULL
|| ad
->len
== 0)
72 return KRB5KDC_ERR_PADATA_TYPE_NOSUPP
;
76 if (ad
->val
[pos
].ad_type
!= KRB5_AUTHDATA_IF_RELEVANT
)
77 return KRB5KDC_ERR_PADATA_TYPE_NOSUPP
;
79 ret
= decode_AuthorizationData(ad
->val
[pos
].ad_data
.data
,
80 ad
->val
[pos
].ad_data
.length
,
84 krb5_set_error_string(context
, "Failed to decode "
85 "IF_RELEVANT with %d", ret
);
90 free_AuthorizationData(&child
);
91 return KRB5KDC_ERR_PADATA_TYPE_NOSUPP
;
94 if (child
.val
[0].ad_type
!= KRB5_AUTHDATA_SIGNTICKET
) {
95 free_AuthorizationData(&child
);
96 return KRB5KDC_ERR_PADATA_TYPE_NOSUPP
;
100 ret
= der_copy_octet_string(&child
.val
[0].ad_data
, data
);
101 free_AuthorizationData(&child
);
106 _kdc_add_KRB5SignedPath(krb5_context context
,
107 krb5_kdc_configuration
*config
,
108 hdb_entry_ex
*krbtgt
,
109 krb5_enctype enctype
,
110 krb5_const_principal server
,
111 KRB5SignedPathPrincipals
*principals
,
117 krb5_crypto crypto
= NULL
;
120 if (server
&& principals
) {
121 ret
= add_KRB5SignedPathPrincipals(principals
, server
);
127 KRB5SignedPathData spd
;
129 spd
.encticket
= *tkt
;
130 spd
.delegated
= principals
;
132 ASN1_MALLOC_ENCODE(KRB5SignedPathData
, data
.data
, data
.length
,
136 if (data
.length
!= size
)
137 krb5_abortx(context
, "internal asn.1 encoder error");
142 ret
= hdb_enctype2key(context
, &krbtgt
->entry
, enctype
, &key
);
144 ret
= krb5_crypto_init(context
, &key
->key
, 0, &crypto
);
152 * Fill in KRB5SignedPath
156 sp
.delegated
= principals
;
158 ret
= krb5_create_checksum(context
, crypto
, KRB5_KU_KRB5SIGNEDPATH
, 0,
159 data
.data
, data
.length
, &sp
.cksum
);
160 krb5_crypto_destroy(context
, crypto
);
165 ASN1_MALLOC_ENCODE(KRB5SignedPath
, data
.data
, data
.length
, &sp
, &size
, ret
);
166 free_Checksum(&sp
.cksum
);
169 if (data
.length
!= size
)
170 krb5_abortx(context
, "internal asn.1 encoder error");
174 * Add IF-RELEVANT(KRB5SignedPath) to the last slot in
175 * authorization data field.
178 ret
= _kdc_tkt_add_if_relevant_ad(context
, tkt
,
179 KRB5_AUTHDATA_SIGNTICKET
, &data
);
180 krb5_data_free(&data
);
185 static krb5_error_code
186 check_KRB5SignedPath(krb5_context context
,
187 krb5_kdc_configuration
*config
,
188 hdb_entry_ex
*krbtgt
,
190 KRB5SignedPathPrincipals
**delegated
,
191 int require_signedpath
)
195 krb5_crypto crypto
= NULL
;
199 ret
= find_KRB5SignedPath(context
, tkt
->authorization_data
, &data
);
201 KRB5SignedPathData spd
;
203 AuthorizationData
*ad
;
206 ret
= decode_KRB5SignedPath(data
.data
, data
.length
, &sp
, NULL
);
207 krb5_data_free(&data
);
211 spd
.encticket
= *tkt
;
212 /* the KRB5SignedPath is the last entry */
213 ad
= spd
.encticket
.authorization_data
;
215 spd
.encticket
.authorization_data
= NULL
;
216 spd
.delegated
= sp
.delegated
;
218 ASN1_MALLOC_ENCODE(KRB5SignedPathData
, data
.data
, data
.length
,
221 spd
.encticket
.authorization_data
= ad
;
223 free_KRB5SignedPath(&sp
);
226 if (data
.length
!= size
)
227 krb5_abortx(context
, "internal asn.1 encoder error");
231 ret
= hdb_enctype2key(context
, &krbtgt
->entry
, sp
.etype
, &key
);
233 ret
= krb5_crypto_init(context
, &key
->key
, 0, &crypto
);
236 free_KRB5SignedPath(&sp
);
240 ret
= krb5_verify_checksum(context
, crypto
, KRB5_KU_KRB5SIGNEDPATH
,
241 data
.data
, data
.length
,
243 krb5_crypto_destroy(context
, crypto
);
246 free_KRB5SignedPath(&sp
);
252 *delegated
= malloc(sizeof(*sp
.delegated
));
253 if (*delegated
== NULL
) {
254 free_KRB5SignedPath(&sp
);
258 ret
= copy_KRB5SignedPathPrincipals(*delegated
, sp
.delegated
);
260 free_KRB5SignedPath(&sp
);
266 free_KRB5SignedPath(&sp
);
269 if (require_signedpath
)
270 return KRB5KDC_ERR_BADOPTION
;
280 static krb5_error_code
281 check_PAC(krb5_context context
,
282 krb5_kdc_configuration
*config
,
283 const krb5_principal client_principal
,
284 hdb_entry_ex
*client
,
285 hdb_entry_ex
*server
,
286 const EncryptionKey
*server_key
,
287 const EncryptionKey
*krbtgt_key
,
290 int *require_signedpath
)
292 AuthorizationData
*ad
= tkt
->authorization_data
;
296 if (ad
== NULL
|| ad
->len
== 0)
299 for (i
= 0; i
< ad
->len
; i
++) {
300 AuthorizationData child
;
302 if (ad
->val
[i
].ad_type
!= KRB5_AUTHDATA_IF_RELEVANT
)
305 ret
= decode_AuthorizationData(ad
->val
[i
].ad_data
.data
,
306 ad
->val
[i
].ad_data
.length
,
310 krb5_set_error_string(context
, "Failed to decode "
311 "IF_RELEVANT with %d", ret
);
314 for (j
= 0; j
< child
.len
; j
++) {
316 if (child
.val
[j
].ad_type
== KRB5_AUTHDATA_WIN2K_PAC
) {
320 ret
= krb5_pac_parse(context
,
321 child
.val
[j
].ad_data
.data
,
322 child
.val
[j
].ad_data
.length
,
324 free_AuthorizationData(&child
);
328 ret
= krb5_pac_verify(context
, pac
, tkt
->authtime
,
332 krb5_pac_free(context
, pac
);
336 ret
= _kdc_pac_verify(context
, client_principal
,
337 client
, server
, &pac
);
339 krb5_pac_free(context
, pac
);
342 *require_signedpath
= 0;
344 ret
= _krb5_pac_sign(context
, pac
, tkt
->authtime
,
346 server_key
, krbtgt_key
, rspac
);
348 krb5_pac_free(context
, pac
);
353 free_AuthorizationData(&child
);
362 static krb5_error_code
363 check_tgs_flags(krb5_context context
,
364 krb5_kdc_configuration
*config
,
365 KDC_REQ_BODY
*b
, const EncTicketPart
*tgt
, EncTicketPart
*et
)
367 KDCOptions f
= b
->kdc_options
;
370 if(!tgt
->flags
.invalid
|| tgt
->starttime
== NULL
){
371 kdc_log(context
, config
, 0,
372 "Bad request to validate ticket");
373 return KRB5KDC_ERR_BADOPTION
;
375 if(*tgt
->starttime
> kdc_time
){
376 kdc_log(context
, config
, 0,
377 "Early request to validate ticket");
378 return KRB5KRB_AP_ERR_TKT_NYV
;
381 et
->flags
.invalid
= 0;
382 }else if(tgt
->flags
.invalid
){
383 kdc_log(context
, config
, 0,
384 "Ticket-granting ticket has INVALID flag set");
385 return KRB5KRB_AP_ERR_TKT_INVALID
;
389 if(!tgt
->flags
.forwardable
){
390 kdc_log(context
, config
, 0,
391 "Bad request for forwardable ticket");
392 return KRB5KDC_ERR_BADOPTION
;
394 et
->flags
.forwardable
= 1;
397 if(!tgt
->flags
.forwardable
){
398 kdc_log(context
, config
, 0,
399 "Request to forward non-forwardable ticket");
400 return KRB5KDC_ERR_BADOPTION
;
402 et
->flags
.forwarded
= 1;
403 et
->caddr
= b
->addresses
;
405 if(tgt
->flags
.forwarded
)
406 et
->flags
.forwarded
= 1;
409 if(!tgt
->flags
.proxiable
){
410 kdc_log(context
, config
, 0,
411 "Bad request for proxiable ticket");
412 return KRB5KDC_ERR_BADOPTION
;
414 et
->flags
.proxiable
= 1;
417 if(!tgt
->flags
.proxiable
){
418 kdc_log(context
, config
, 0,
419 "Request to proxy non-proxiable ticket");
420 return KRB5KDC_ERR_BADOPTION
;
423 et
->caddr
= b
->addresses
;
428 if(f
.allow_postdate
){
429 if(!tgt
->flags
.may_postdate
){
430 kdc_log(context
, config
, 0,
431 "Bad request for post-datable ticket");
432 return KRB5KDC_ERR_BADOPTION
;
434 et
->flags
.may_postdate
= 1;
437 if(!tgt
->flags
.may_postdate
){
438 kdc_log(context
, config
, 0,
439 "Bad request for postdated ticket");
440 return KRB5KDC_ERR_BADOPTION
;
443 *et
->starttime
= *b
->from
;
444 et
->flags
.postdated
= 1;
445 et
->flags
.invalid
= 1;
446 }else if(b
->from
&& *b
->from
> kdc_time
+ context
->max_skew
){
447 kdc_log(context
, config
, 0, "Ticket cannot be postdated");
448 return KRB5KDC_ERR_CANNOT_POSTDATE
;
452 if(!tgt
->flags
.renewable
){
453 kdc_log(context
, config
, 0,
454 "Bad request for renewable ticket");
455 return KRB5KDC_ERR_BADOPTION
;
457 et
->flags
.renewable
= 1;
458 ALLOC(et
->renew_till
);
459 _kdc_fix_time(&b
->rtime
);
460 *et
->renew_till
= *b
->rtime
;
464 if(!tgt
->flags
.renewable
|| tgt
->renew_till
== NULL
){
465 kdc_log(context
, config
, 0,
466 "Request to renew non-renewable ticket");
467 return KRB5KDC_ERR_BADOPTION
;
469 old_life
= tgt
->endtime
;
471 old_life
-= *tgt
->starttime
;
473 old_life
-= tgt
->authtime
;
474 et
->endtime
= *et
->starttime
+ old_life
;
475 if (et
->renew_till
!= NULL
)
476 et
->endtime
= min(*et
->renew_till
, et
->endtime
);
480 /* checks for excess flags */
481 if(f
.request_anonymous
&& !config
->allow_anonymous
){
482 kdc_log(context
, config
, 0,
483 "Request for anonymous ticket");
484 return KRB5KDC_ERR_BADOPTION
;
494 static krb5_error_code
495 check_constrained_delegation(krb5_context context
,
496 krb5_kdc_configuration
*config
,
497 hdb_entry_ex
*client
,
498 krb5_const_principal server
)
500 const HDB_Ext_Constrained_delegation_acl
*acl
;
504 ret
= hdb_entry_get_ConstrainedDelegACL(&client
->entry
, &acl
);
506 krb5_clear_error_string(context
);
511 for (i
= 0; i
< acl
->len
; i
++) {
512 if (krb5_principal_compare(context
, server
, &acl
->val
[i
]) == TRUE
)
516 kdc_log(context
, config
, 0,
517 "Bad request for constrained delegation");
518 return KRB5KDC_ERR_BADOPTION
;
525 static krb5_error_code
526 verify_flags (krb5_context context
,
527 krb5_kdc_configuration
*config
,
528 const EncTicketPart
*et
,
531 if(et
->endtime
< kdc_time
){
532 kdc_log(context
, config
, 0, "Ticket expired (%s)", pstr
);
533 return KRB5KRB_AP_ERR_TKT_EXPIRED
;
535 if(et
->flags
.invalid
){
536 kdc_log(context
, config
, 0, "Ticket not valid (%s)", pstr
);
537 return KRB5KRB_AP_ERR_TKT_NYV
;
546 static krb5_error_code
547 fix_transited_encoding(krb5_context context
,
548 krb5_kdc_configuration
*config
,
549 krb5_boolean check_policy
,
550 const TransitedEncoding
*tr
,
552 const char *client_realm
,
553 const char *server_realm
,
554 const char *tgt_realm
)
556 krb5_error_code ret
= 0;
557 char **realms
, **tmp
;
561 switch (tr
->tr_type
) {
562 case DOMAIN_X500_COMPRESS
:
566 * Allow empty content of type 0 because that is was Microsoft
567 * generates in their TGT.
569 if (tr
->contents
.length
== 0)
571 kdc_log(context
, config
, 0,
572 "Transited type 0 with non empty content");
573 return KRB5KDC_ERR_TRTYPE_NOSUPP
;
575 kdc_log(context
, config
, 0,
576 "Unknown transited type: %u", tr
->tr_type
);
577 return KRB5KDC_ERR_TRTYPE_NOSUPP
;
580 ret
= krb5_domain_x500_decode(context
,
587 krb5_warn(context
, ret
,
588 "Decoding transited encoding");
591 if(strcmp(client_realm
, tgt_realm
) && strcmp(server_realm
, tgt_realm
)) {
592 /* not us, so add the previous realm to transited set */
593 if (num_realms
< 0 || num_realms
+ 1 > UINT_MAX
/sizeof(*realms
)) {
597 tmp
= realloc(realms
, (num_realms
+ 1) * sizeof(*realms
));
603 realms
[num_realms
] = strdup(tgt_realm
);
604 if(realms
[num_realms
] == NULL
){
610 if(num_realms
== 0) {
611 if(strcmp(client_realm
, server_realm
))
612 kdc_log(context
, config
, 0,
613 "cross-realm %s -> %s", client_realm
, server_realm
);
617 for(i
= 0; i
< num_realms
; i
++)
618 l
+= strlen(realms
[i
]) + 2;
622 for(i
= 0; i
< num_realms
; i
++) {
624 strlcat(rs
, ", ", l
);
625 strlcat(rs
, realms
[i
], l
);
627 kdc_log(context
, config
, 0,
628 "cross-realm %s -> %s via [%s]",
629 client_realm
, server_realm
, rs
);
634 ret
= krb5_check_transited(context
, client_realm
,
636 realms
, num_realms
, NULL
);
638 krb5_warn(context
, ret
, "cross-realm %s -> %s",
639 client_realm
, server_realm
);
642 et
->flags
.transited_policy_checked
= 1;
644 et
->transited
.tr_type
= DOMAIN_X500_COMPRESS
;
645 ret
= krb5_domain_x500_encode(realms
, num_realms
, &et
->transited
.contents
);
647 krb5_warn(context
, ret
, "Encoding transited encoding");
649 for(i
= 0; i
< num_realms
; i
++)
656 static krb5_error_code
657 tgs_make_reply(krb5_context context
,
658 krb5_kdc_configuration
*config
,
660 krb5_const_principal tgt_name
,
661 const EncTicketPart
*tgt
,
662 const EncryptionKey
*serverkey
,
663 const krb5_keyblock
*sessionkey
,
665 AuthorizationData
*auth_data
,
666 hdb_entry_ex
*server
,
667 const char *server_name
,
668 hdb_entry_ex
*client
,
669 krb5_principal client_principal
,
670 hdb_entry_ex
*krbtgt
,
671 krb5_enctype krbtgt_etype
,
672 KRB5SignedPathPrincipals
*spp
,
673 const krb5_data
*rspac
,
680 KDCOptions f
= b
->kdc_options
;
683 memset(&rep
, 0, sizeof(rep
));
684 memset(&et
, 0, sizeof(et
));
685 memset(&ek
, 0, sizeof(ek
));
688 rep
.msg_type
= krb_tgs_rep
;
690 et
.authtime
= tgt
->authtime
;
691 _kdc_fix_time(&b
->till
);
692 et
.endtime
= min(tgt
->endtime
, *b
->till
);
694 *et
.starttime
= kdc_time
;
696 ret
= check_tgs_flags(context
, config
, b
, tgt
, &et
);
700 /* We should check the transited encoding if:
701 1) the request doesn't ask not to be checked
702 2) globally enforcing a check
703 3) principal requires checking
704 4) we allow non-check per-principal, but principal isn't marked as allowing this
705 5) we don't globally allow this
708 #define GLOBAL_FORCE_TRANSITED_CHECK \
709 (config->trpolicy == TRPOLICY_ALWAYS_CHECK)
710 #define GLOBAL_ALLOW_PER_PRINCIPAL \
711 (config->trpolicy == TRPOLICY_ALLOW_PER_PRINCIPAL)
712 #define GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK \
713 (config->trpolicy == TRPOLICY_ALWAYS_HONOUR_REQUEST)
715 /* these will consult the database in future release */
716 #define PRINCIPAL_FORCE_TRANSITED_CHECK(P) 0
717 #define PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(P) 0
719 ret
= fix_transited_encoding(context
, config
,
720 !f
.disable_transited_check
||
721 GLOBAL_FORCE_TRANSITED_CHECK
||
722 PRINCIPAL_FORCE_TRANSITED_CHECK(server
) ||
723 !((GLOBAL_ALLOW_PER_PRINCIPAL
&&
724 PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server
)) ||
725 GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK
),
726 &tgt
->transited
, &et
,
727 *krb5_princ_realm(context
, client_principal
),
728 *krb5_princ_realm(context
, server
->entry
.principal
),
729 *krb5_princ_realm(context
, krbtgt
->entry
.principal
));
733 copy_Realm(krb5_princ_realm(context
, server
->entry
.principal
),
735 _krb5_principal2principalname(&rep
.ticket
.sname
, server
->entry
.principal
);
736 copy_Realm(&tgt_name
->realm
, &rep
.crealm
);
738 if (f.request_anonymous)
739 _kdc_make_anonymous_principalname (&rep.cname);
742 copy_PrincipalName(&tgt_name
->name
, &rep
.cname
);
743 rep
.ticket
.tkt_vno
= 5;
747 et
.caddr
= tgt
->caddr
;
751 life
= et
.endtime
- *et
.starttime
;
752 if(client
&& client
->entry
.max_life
)
753 life
= min(life
, *client
->entry
.max_life
);
754 if(server
->entry
.max_life
)
755 life
= min(life
, *server
->entry
.max_life
);
756 et
.endtime
= *et
.starttime
+ life
;
758 if(f
.renewable_ok
&& tgt
->flags
.renewable
&&
759 et
.renew_till
== NULL
&& et
.endtime
< *b
->till
){
760 et
.flags
.renewable
= 1;
761 ALLOC(et
.renew_till
);
762 *et
.renew_till
= *b
->till
;
766 renew
= *et
.renew_till
- et
.authtime
;
767 if(client
&& client
->entry
.max_renew
)
768 renew
= min(renew
, *client
->entry
.max_renew
);
769 if(server
->entry
.max_renew
)
770 renew
= min(renew
, *server
->entry
.max_renew
);
771 *et
.renew_till
= et
.authtime
+ renew
;
775 *et
.renew_till
= min(*et
.renew_till
, *tgt
->renew_till
);
776 *et
.starttime
= min(*et
.starttime
, *et
.renew_till
);
777 et
.endtime
= min(et
.endtime
, *et
.renew_till
);
780 *et
.starttime
= min(*et
.starttime
, et
.endtime
);
782 if(*et
.starttime
== et
.endtime
){
783 ret
= KRB5KDC_ERR_NEVER_VALID
;
786 if(et
.renew_till
&& et
.endtime
== *et
.renew_till
){
788 et
.renew_till
= NULL
;
789 et
.flags
.renewable
= 0;
792 et
.flags
.pre_authent
= tgt
->flags
.pre_authent
;
793 et
.flags
.hw_authent
= tgt
->flags
.hw_authent
;
794 et
.flags
.anonymous
= tgt
->flags
.anonymous
;
795 et
.flags
.ok_as_delegate
= server
->entry
.flags
.ok_as_delegate
;
798 /* XXX Check enc-authorization-data */
799 et
.authorization_data
= calloc(1, sizeof(*et
.authorization_data
));
800 if (et
.authorization_data
== NULL
) {
804 ret
= copy_AuthorizationData(auth_data
, et
.authorization_data
);
808 /* Filter out type KRB5SignedPath */
809 ret
= find_KRB5SignedPath(context
, et
.authorization_data
, NULL
);
811 if (et
.authorization_data
->len
== 1) {
812 free_AuthorizationData(et
.authorization_data
);
813 free(et
.authorization_data
);
814 et
.authorization_data
= NULL
;
816 AuthorizationData
*ad
= et
.authorization_data
;
817 free_AuthorizationDataElement(&ad
->val
[ad
->len
- 1]);
825 * No not need to filter out the any PAC from the
826 * auth_data since it's signed by the KDC.
828 ret
= _kdc_tkt_add_if_relevant_ad(context
, &et
,
829 KRB5_AUTHDATA_WIN2K_PAC
,
835 ret
= krb5_copy_keyblock_contents(context
, sessionkey
, &et
.key
);
838 et
.crealm
= tgt
->crealm
;
839 et
.cname
= tgt_name
->name
;
842 /* MIT must have at least one last_req */
844 ek
.last_req
.val
= calloc(1, sizeof(*ek
.last_req
.val
));
845 if (ek
.last_req
.val
== NULL
) {
851 ek
.authtime
= et
.authtime
;
852 ek
.starttime
= et
.starttime
;
853 ek
.endtime
= et
.endtime
;
854 ek
.renew_till
= et
.renew_till
;
855 ek
.srealm
= rep
.ticket
.realm
;
856 ek
.sname
= rep
.ticket
.sname
;
858 _kdc_log_timestamp(context
, config
, "TGS-REQ", et
.authtime
, et
.starttime
,
859 et
.endtime
, et
.renew_till
);
861 /* Don't sign cross realm tickets, they can't be checked anyway */
863 char *r
= get_krbtgt_realm(&ek
.sname
);
865 if (r
== NULL
|| strcmp(r
, ek
.srealm
) == 0) {
866 ret
= _kdc_add_KRB5SignedPath(context
,
878 /* It is somewhat unclear where the etype in the following
879 encryption should come from. What we have is a session
880 key in the passed tgt, and a list of preferred etypes
881 *for the new ticket*. Should we pick the best possible
882 etype, given the keytype in the tgt, or should we look
883 at the etype list here as well? What if the tgt
884 session key is DES3 and we want a ticket with a (say)
885 CAST session key. Should the DES3 etype be added to the
886 etype list, even if we don't want a session key with
888 ret
= _kdc_encode_reply(context
, config
,
889 &rep
, &et
, &ek
, et
.key
.keytype
,
891 serverkey
, 0, &tgt
->key
, e_text
, reply
);
894 free_TransitedEncoding(&et
.transited
);
899 if(et
.authorization_data
) {
900 free_AuthorizationData(et
.authorization_data
);
901 free(et
.authorization_data
);
903 free_LastReq(&ek
.last_req
);
904 memset(et
.key
.keyvalue
.data
, 0, et
.key
.keyvalue
.length
);
905 free_EncryptionKey(&et
.key
);
909 static krb5_error_code
910 tgs_check_authenticator(krb5_context context
,
911 krb5_kdc_configuration
*config
,
912 krb5_auth_context ac
,
917 krb5_authenticator auth
;
924 krb5_auth_con_getauthenticator(context
, ac
, &auth
);
925 if(auth
->cksum
== NULL
){
926 kdc_log(context
, config
, 0, "No authenticator in request");
927 ret
= KRB5KRB_AP_ERR_INAPP_CKSUM
;
931 * according to RFC1510 it doesn't need to be keyed,
932 * but according to the latest draft it needs to.
936 !krb5_checksum_is_keyed(context
, auth
->cksum
->cksumtype
)
939 !krb5_checksum_is_collision_proof(context
, auth
->cksum
->cksumtype
)) {
940 kdc_log(context
, config
, 0, "Bad checksum type in authenticator: %d",
941 auth
->cksum
->cksumtype
);
942 ret
= KRB5KRB_AP_ERR_INAPP_CKSUM
;
946 /* XXX should not re-encode this */
947 ASN1_MALLOC_ENCODE(KDC_REQ_BODY
, buf
, buf_size
, b
, &len
, ret
);
949 kdc_log(context
, config
, 0, "Failed to encode KDC-REQ-BODY: %s",
950 krb5_get_err_text(context
, ret
));
953 if(buf_size
!= len
) {
955 kdc_log(context
, config
, 0, "Internal error in ASN.1 encoder");
956 *e_text
= "KDC internal error";
957 ret
= KRB5KRB_ERR_GENERIC
;
960 ret
= krb5_crypto_init(context
, key
, 0, &crypto
);
963 kdc_log(context
, config
, 0, "krb5_crypto_init failed: %s",
964 krb5_get_err_text(context
, ret
));
967 ret
= krb5_verify_checksum(context
,
969 KRB5_KU_TGS_REQ_AUTH_CKSUM
,
974 krb5_crypto_destroy(context
, crypto
);
976 kdc_log(context
, config
, 0,
977 "Failed to verify authenticator checksum: %s",
978 krb5_get_err_text(context
, ret
));
981 free_Authenticator(auth
);
991 find_rpath(krb5_context context
, Realm crealm
, Realm srealm
)
993 const char *new_realm
= krb5_config_get_string(context
,
1004 need_referral(krb5_context context
, krb5_principal server
, krb5_realm
**realms
)
1006 if(server
->name
.name_type
!= KRB5_NT_SRV_INST
||
1007 server
->name
.name_string
.len
!= 2)
1010 return _krb5_get_host_realm_int(context
, server
->name
.name_string
.val
[1],
1011 FALSE
, realms
) == 0;
1014 static krb5_error_code
1015 tgs_parse_request(krb5_context context
,
1016 krb5_kdc_configuration
*config
,
1018 const PA_DATA
*tgs_req
,
1019 hdb_entry_ex
**krbtgt
,
1020 krb5_enctype
*krbtgt_etype
,
1021 krb5_ticket
**ticket
,
1022 const char **e_text
,
1024 const struct sockaddr
*from_addr
,
1027 AuthorizationData
**auth_data
)
1030 krb5_error_code ret
;
1031 krb5_principal princ
;
1032 krb5_auth_context ac
= NULL
;
1033 krb5_flags ap_req_options
;
1034 krb5_flags verify_ap_req_flags
;
1042 memset(&ap_req
, 0, sizeof(ap_req
));
1043 ret
= krb5_decode_ap_req(context
, &tgs_req
->padata_value
, &ap_req
);
1045 kdc_log(context
, config
, 0, "Failed to decode AP-REQ: %s",
1046 krb5_get_err_text(context
, ret
));
1050 if(!get_krbtgt_realm(&ap_req
.ticket
.sname
)){
1051 /* XXX check for ticket.sname == req.sname */
1052 kdc_log(context
, config
, 0, "PA-DATA is not a ticket-granting ticket");
1053 ret
= KRB5KDC_ERR_POLICY
; /* ? */
1057 _krb5_principalname2krb5_principal(context
,
1059 ap_req
.ticket
.sname
,
1060 ap_req
.ticket
.realm
);
1062 ret
= _kdc_db_fetch(context
, config
, princ
, HDB_F_GET_KRBTGT
, NULL
, krbtgt
);
1066 ret
= krb5_unparse_name(context
, princ
, &p
);
1068 p
= "<unparse_name failed>";
1069 krb5_free_principal(context
, princ
);
1070 kdc_log(context
, config
, 0,
1071 "Ticket-granting ticket not found in database: %s: %s",
1072 p
, krb5_get_err_text(context
, ret
));
1075 ret
= KRB5KRB_AP_ERR_NOT_US
;
1079 if(ap_req
.ticket
.enc_part
.kvno
&&
1080 *ap_req
.ticket
.enc_part
.kvno
!= (*krbtgt
)->entry
.kvno
){
1083 ret
= krb5_unparse_name (context
, princ
, &p
);
1084 krb5_free_principal(context
, princ
);
1086 p
= "<unparse_name failed>";
1087 kdc_log(context
, config
, 0,
1088 "Ticket kvno = %d, DB kvno = %d (%s)",
1089 *ap_req
.ticket
.enc_part
.kvno
,
1090 (*krbtgt
)->entry
.kvno
,
1094 ret
= KRB5KRB_AP_ERR_BADKEYVER
;
1098 *krbtgt_etype
= ap_req
.ticket
.enc_part
.etype
;
1100 ret
= hdb_enctype2key(context
, &(*krbtgt
)->entry
,
1101 ap_req
.ticket
.enc_part
.etype
, &tkey
);
1103 char *str
= NULL
, *p
= NULL
;
1105 krb5_enctype_to_string(context
, ap_req
.ticket
.enc_part
.etype
, &str
);
1106 krb5_unparse_name(context
, princ
, &p
);
1107 kdc_log(context
, config
, 0,
1108 "No server key with enctype %s found for %s",
1109 str
? str
: "<unknown enctype>",
1110 p
? p
: "<unparse_name failed>");
1113 ret
= KRB5KRB_AP_ERR_BADKEYVER
;
1117 if (b
->kdc_options
.validate
)
1118 verify_ap_req_flags
= KRB5_VERIFY_AP_REQ_IGNORE_INVALID
;
1120 verify_ap_req_flags
= 0;
1122 ret
= krb5_verify_ap_req2(context
,
1127 verify_ap_req_flags
,
1130 KRB5_KU_TGS_REQ_AUTH
);
1132 krb5_free_principal(context
, princ
);
1134 kdc_log(context
, config
, 0, "Failed to verify AP-REQ: %s",
1135 krb5_get_err_text(context
, ret
));
1140 krb5_authenticator auth
;
1142 ret
= krb5_auth_con_getauthenticator(context
, ac
, &auth
);
1144 *csec
= malloc(sizeof(**csec
));
1145 if (*csec
== NULL
) {
1146 krb5_free_authenticator(context
, &auth
);
1147 kdc_log(context
, config
, 0, "malloc failed");
1150 **csec
= auth
->ctime
;
1151 *cusec
= malloc(sizeof(**cusec
));
1152 if (*cusec
== NULL
) {
1153 krb5_free_authenticator(context
, &auth
);
1154 kdc_log(context
, config
, 0, "malloc failed");
1157 **cusec
= auth
->cusec
;
1158 krb5_free_authenticator(context
, &auth
);
1162 ret
= tgs_check_authenticator(context
, config
,
1163 ac
, b
, e_text
, &(*ticket
)->ticket
.key
);
1165 krb5_auth_con_free(context
, ac
);
1169 if (b
->enc_authorization_data
) {
1170 unsigned usage
= KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY
;
1171 krb5_keyblock
*subkey
;
1174 ret
= krb5_auth_con_getremotesubkey(context
,
1178 krb5_auth_con_free(context
, ac
);
1179 kdc_log(context
, config
, 0, "Failed to get remote subkey: %s",
1180 krb5_get_err_text(context
, ret
));
1184 usage
= KRB5_KU_TGS_REQ_AUTH_DAT_SESSION
;
1185 ret
= krb5_auth_con_getkey(context
, ac
, &subkey
);
1187 krb5_auth_con_free(context
, ac
);
1188 kdc_log(context
, config
, 0, "Failed to get session key: %s",
1189 krb5_get_err_text(context
, ret
));
1194 krb5_auth_con_free(context
, ac
);
1195 kdc_log(context
, config
, 0,
1196 "Failed to get key for enc-authorization-data");
1197 ret
= KRB5KRB_AP_ERR_BAD_INTEGRITY
; /* ? */
1200 ret
= krb5_crypto_init(context
, subkey
, 0, &crypto
);
1202 krb5_auth_con_free(context
, ac
);
1203 kdc_log(context
, config
, 0, "krb5_crypto_init failed: %s",
1204 krb5_get_err_text(context
, ret
));
1207 ret
= krb5_decrypt_EncryptedData (context
,
1210 b
->enc_authorization_data
,
1212 krb5_crypto_destroy(context
, crypto
);
1214 krb5_auth_con_free(context
, ac
);
1215 kdc_log(context
, config
, 0,
1216 "Failed to decrypt enc-authorization-data");
1217 ret
= KRB5KRB_AP_ERR_BAD_INTEGRITY
; /* ? */
1220 krb5_free_keyblock(context
, subkey
);
1222 if (*auth_data
== NULL
) {
1223 krb5_auth_con_free(context
, ac
);
1224 ret
= KRB5KRB_AP_ERR_BAD_INTEGRITY
; /* ? */
1227 ret
= decode_AuthorizationData(ad
.data
, ad
.length
, *auth_data
, NULL
);
1229 krb5_auth_con_free(context
, ac
);
1232 kdc_log(context
, config
, 0, "Failed to decode authorization data");
1233 ret
= KRB5KRB_AP_ERR_BAD_INTEGRITY
; /* ? */
1238 krb5_auth_con_free(context
, ac
);
1241 free_AP_REQ(&ap_req
);
1246 static krb5_error_code
1247 tgs_build_reply(krb5_context context
,
1248 krb5_kdc_configuration
*config
,
1251 hdb_entry_ex
*krbtgt
,
1252 krb5_enctype krbtgt_etype
,
1253 krb5_ticket
*ticket
,
1256 const char **e_text
,
1257 AuthorizationData
*auth_data
,
1258 const struct sockaddr
*from_addr
,
1261 krb5_error_code ret
;
1262 krb5_principal cp
= NULL
, sp
= NULL
;
1263 krb5_principal client_principal
= NULL
;
1264 char *spn
= NULL
, *cpn
= NULL
;
1265 hdb_entry_ex
*server
= NULL
, *client
= NULL
;
1266 EncTicketPart
*tgt
= &ticket
->ticket
;
1267 KRB5SignedPathPrincipals
*spp
= NULL
;
1268 const EncryptionKey
*ekey
;
1269 krb5_keyblock sessionkey
;
1272 int cross_realm
= 0;
1277 EncTicketPart adtkt
;
1279 int require_signedpath
= 0;
1281 memset(&sessionkey
, 0, sizeof(sessionkey
));
1282 memset(&adtkt
, 0, sizeof(adtkt
));
1283 krb5_data_zero(&rspac
);
1288 if(b
->kdc_options
.enc_tkt_in_skey
){
1294 if(b
->additional_tickets
== NULL
||
1295 b
->additional_tickets
->len
== 0){
1296 ret
= KRB5KDC_ERR_BADOPTION
; /* ? */
1297 kdc_log(context
, config
, 0,
1298 "No second ticket present in request");
1301 t
= &b
->additional_tickets
->val
[0];
1302 if(!get_krbtgt_realm(&t
->sname
)){
1303 kdc_log(context
, config
, 0,
1304 "Additional ticket is not a ticket-granting ticket");
1305 ret
= KRB5KDC_ERR_POLICY
;
1308 _krb5_principalname2krb5_principal(context
, &p
, t
->sname
, t
->realm
);
1309 ret
= _kdc_db_fetch(context
, config
, p
,
1310 HDB_F_GET_CLIENT
|HDB_F_GET_SERVER
,
1312 krb5_free_principal(context
, p
);
1314 if (ret
== HDB_ERR_NOENTRY
)
1315 ret
= KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
;
1318 ret
= hdb_enctype2key(context
, &uu
->entry
,
1319 t
->enc_part
.etype
, &uukey
);
1321 _kdc_free_ent(context
, uu
);
1322 ret
= KRB5KDC_ERR_ETYPE_NOSUPP
; /* XXX */
1325 ret
= krb5_decrypt_ticket(context
, t
, &uukey
->key
, &adtkt
, 0);
1326 _kdc_free_ent(context
, uu
);
1330 ret
= verify_flags(context
, config
, &adtkt
, spn
);
1338 _krb5_principalname2krb5_principal(context
, &sp
, *s
, r
);
1339 ret
= krb5_unparse_name(context
, sp
, &spn
);
1342 _krb5_principalname2krb5_principal(context
, &cp
, tgt
->cname
, tgt
->crealm
);
1343 ret
= krb5_unparse_name(context
, cp
, &cpn
);
1346 unparse_flags (KDCOptions2int(b
->kdc_options
),
1347 asn1_KDCOptions_units(),
1348 opt_str
, sizeof(opt_str
));
1350 kdc_log(context
, config
, 0,
1351 "TGS-REQ %s from %s for %s [%s]",
1352 cpn
, from
, spn
, opt_str
);
1354 kdc_log(context
, config
, 0,
1355 "TGS-REQ %s from %s for %s", cpn
, from
, spn
);
1362 ret
= _kdc_db_fetch(context
, config
, sp
, HDB_F_GET_SERVER
, NULL
, &server
);
1365 const char *new_rlm
;
1369 if ((req_rlm
= get_krbtgt_realm(&sp
->name
)) != NULL
) {
1371 new_rlm
= find_rpath(context
, tgt
->crealm
, req_rlm
);
1373 kdc_log(context
, config
, 5, "krbtgt for realm %s "
1374 "not found, trying %s",
1376 krb5_free_principal(context
, sp
);
1378 krb5_make_principal(context
, &sp
, r
,
1379 KRB5_TGS_NAME
, new_rlm
, NULL
);
1380 ret
= krb5_unparse_name(context
, sp
, &spn
);
1383 auth_data
= NULL
; /* ms don't handle AD in referals */
1387 } else if(need_referral(context
, sp
, &realms
)) {
1388 if (strcmp(realms
[0], sp
->realm
) != 0) {
1389 kdc_log(context
, config
, 5,
1390 "Returning a referral to realm %s for "
1391 "server %s that was not found",
1393 krb5_free_principal(context
, sp
);
1395 krb5_make_principal(context
, &sp
, r
, KRB5_TGS_NAME
,
1397 ret
= krb5_unparse_name(context
, sp
, &spn
);
1400 krb5_free_host_realm(context
, realms
);
1401 auth_data
= NULL
; /* ms don't handle AD in referals */
1404 krb5_free_host_realm(context
, realms
);
1406 kdc_log(context
, config
, 0,
1407 "Server not found in database: %s: %s", spn
,
1408 krb5_get_err_text(context
, ret
));
1409 if (ret
== HDB_ERR_NOENTRY
)
1410 ret
= KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
;
1414 ret
= _kdc_db_fetch(context
, config
, cp
, HDB_F_GET_CLIENT
, NULL
, &client
);
1416 const char *krbtgt_realm
;
1419 * If the client belongs to the same realm as our krbtgt, it
1420 * should exist in the local database.
1425 krb5_principal_get_comp_string(context
,
1426 krbtgt
->entry
.principal
, 1);
1428 if(strcmp(krb5_principal_get_realm(context
, cp
), krbtgt_realm
) == 0) {
1429 if (ret
== HDB_ERR_NOENTRY
)
1430 ret
= KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN
;
1431 kdc_log(context
, config
, 1, "Client no longer in database: %s",
1436 kdc_log(context
, config
, 1, "Client not found in database: %s: %s",
1437 cpn
, krb5_get_err_text(context
, ret
));
1443 * Check that service is in the same realm as the krbtgt. If it's
1444 * not the same, it's someone that is using a uni-directional trust
1448 if (strcmp(krb5_principal_get_realm(context
, sp
),
1449 krb5_principal_get_comp_string(context
,
1450 krbtgt
->entry
.principal
,
1453 ret
= krb5_unparse_name(context
, krbtgt
->entry
.principal
, &tpn
);
1454 kdc_log(context
, config
, 0,
1455 "Request with wrong krbtgt: %s",
1456 (ret
== 0) ? tpn
: "<unknown>");
1459 ret
= KRB5KRB_AP_ERR_NOT_US
;
1467 client_principal
= cp
;
1470 const PA_DATA
*sdata
;
1473 sdata
= _kdc_find_padata(req
, &i
, KRB5_PADATA_S4U2SELF
);
1478 char *selfcpn
= NULL
;
1481 ret
= decode_PA_S4U2Self(sdata
->padata_value
.data
,
1482 sdata
->padata_value
.length
,
1485 kdc_log(context
, config
, 0, "Failed to decode PA-S4U2Self");
1489 ret
= _krb5_s4u2self_to_checksumdata(context
, &self
, &datack
);
1493 ret
= krb5_crypto_init(context
, &tgt
->key
, 0, &crypto
);
1495 free_PA_S4U2Self(&self
);
1496 krb5_data_free(&datack
);
1497 kdc_log(context
, config
, 0, "krb5_crypto_init failed: %s",
1498 krb5_get_err_text(context
, ret
));
1502 ret
= krb5_verify_checksum(context
,
1504 KRB5_KU_OTHER_CKSUM
,
1508 krb5_data_free(&datack
);
1509 krb5_crypto_destroy(context
, crypto
);
1511 free_PA_S4U2Self(&self
);
1512 kdc_log(context
, config
, 0,
1513 "krb5_verify_checksum failed for S4U2Self: %s",
1514 krb5_get_err_text(context
, ret
));
1518 ret
= _krb5_principalname2krb5_principal(context
,
1522 free_PA_S4U2Self(&self
);
1526 ret
= krb5_unparse_name(context
, client_principal
, &selfcpn
);
1531 * Check that service doing the impersonating is
1532 * requesting a ticket to it-self.
1534 if (krb5_principal_compare(context
, cp
, sp
) != TRUE
) {
1535 kdc_log(context
, config
, 0, "S4U2Self: %s is not allowed "
1536 "to impersonate some other user "
1537 "(tried for user %s to service %s)",
1540 ret
= KRB5KDC_ERR_BADOPTION
; /* ? */
1545 * If the service isn't trusted for authentication to
1546 * delegation, remove the forward flag.
1549 if (client
->entry
.flags
.trusted_for_delegation
) {
1550 str
= "[forwardable]";
1552 b
->kdc_options
.forwardable
= 0;
1555 kdc_log(context
, config
, 0, "s4u2self %s impersonating %s to "
1556 "service %s %s", cpn
, selfcpn
, spn
, str
);
1562 * Constrained delegation
1566 && b
->additional_tickets
!= NULL
1567 && b
->additional_tickets
->len
!= 0
1568 && b
->kdc_options
.enc_tkt_in_skey
== 0)
1574 t
= &b
->additional_tickets
->val
[0];
1576 ret
= hdb_enctype2key(context
, &client
->entry
,
1577 t
->enc_part
.etype
, &clientkey
);
1579 ret
= KRB5KDC_ERR_ETYPE_NOSUPP
; /* XXX */
1583 ret
= krb5_decrypt_ticket(context
, t
, &clientkey
->key
, &adtkt
, 0);
1585 kdc_log(context
, config
, 0,
1586 "failed to decrypt ticket for "
1587 "constrained delegation from %s to %s ", spn
, cpn
);
1591 /* check that ticket is valid */
1593 if (adtkt
.flags
.forwardable
== 0) {
1594 kdc_log(context
, config
, 0,
1595 "Missing forwardable flag on ticket for "
1596 "constrained delegation from %s to %s ", spn
, cpn
);
1597 ret
= KRB5KDC_ERR_ETYPE_NOSUPP
; /* XXX */
1601 ret
= check_constrained_delegation(context
, config
, client
, sp
);
1603 kdc_log(context
, config
, 0,
1604 "constrained delegation from %s to %s not allowed",
1609 ret
= _krb5_principalname2krb5_principal(context
,
1616 ret
= krb5_unparse_name(context
, client_principal
, &str
);
1620 ret
= verify_flags(context
, config
, &adtkt
, str
);
1627 * Check KRB5SignedPath in authorization data and add new entry to
1628 * make sure servers can't fake a ticket to us.
1631 ret
= check_KRB5SignedPath(context
,
1638 kdc_log(context
, config
, 0,
1639 "KRB5SignedPath check from service %s failed "
1640 "for delegation to %s for client %s "
1641 "from %s failed with %s",
1642 spn
, str
, cpn
, from
, krb5_get_err_text(context
, ret
));
1647 kdc_log(context
, config
, 0, "constrained delegation for %s "
1648 "from %s to %s", str
, cpn
, spn
);
1652 * Also require that the KDC have issue the service's krbtgt
1653 * used to do the request.
1655 require_signedpath
= 1;
1662 ret
= _kdc_check_flags(context
, config
,
1669 if((b
->kdc_options
.validate
|| b
->kdc_options
.renew
) &&
1670 !krb5_principal_compare(context
,
1671 krbtgt
->entry
.principal
,
1672 server
->entry
.principal
)){
1673 kdc_log(context
, config
, 0, "Inconsistent request.");
1674 ret
= KRB5KDC_ERR_SERVER_NOMATCH
;
1678 /* check for valid set of addresses */
1679 if(!_kdc_check_addresses(context
, config
, tgt
->caddr
, from_addr
)) {
1680 ret
= KRB5KRB_AP_ERR_BADADDR
;
1681 kdc_log(context
, config
, 0, "Request from wrong address");
1686 * Select enctype, return key and kvno.
1692 if(b
->kdc_options
.enc_tkt_in_skey
) {
1695 for(i
= 0; i
< b
->etype
.len
; i
++)
1696 if (b
->etype
.val
[i
] == adtkt
.key
.keytype
)
1698 if(i
== b
->etype
.len
) {
1699 krb5_clear_error_string(context
);
1700 krb5_free_principal(context
, client_principal
);
1701 return KRB5KDC_ERR_ETYPE_NOSUPP
;
1703 etype
= b
->etype
.val
[i
];
1708 ret
= _kdc_find_etype(context
, server
, b
->etype
.val
, b
->etype
.len
,
1711 kdc_log(context
, config
, 0,
1712 "Server (%s) has no support for etypes", spp
);
1716 kvno
= server
->entry
.kvno
;
1719 ret
= krb5_generate_random_keyblock(context
, etype
, &sessionkey
);
1724 /* check PAC if not cross realm and if there is one */
1728 ret
= hdb_enctype2key(context
, &krbtgt
->entry
,
1729 krbtgt_etype
, &tkey
);
1731 kdc_log(context
, config
, 0,
1732 "Failed to find key for krbtgt PAC check");
1736 ret
= check_PAC(context
, config
, client_principal
,
1737 client
, server
, ekey
, &tkey
->key
,
1738 tgt
, &rspac
, &require_signedpath
);
1740 kdc_log(context
, config
, 0,
1741 "Verify PAC failed for %s (%s) from %s with %s",
1742 spn
, cpn
, from
, krb5_get_err_text(context
, ret
));
1747 /* also check the krbtgt for signature */
1748 ret
= check_KRB5SignedPath(context
,
1753 require_signedpath
);
1755 kdc_log(context
, config
, 0,
1756 "KRB5SignedPath check failed for %s (%s) from %s with %s",
1757 spn
, cpn
, from
, krb5_get_err_text(context
, ret
));
1765 ret
= tgs_make_reply(context
,
1789 krb5_data_free(&rspac
);
1790 krb5_free_keyblock_contents(context
, &sessionkey
);
1792 _kdc_free_ent(context
, server
);
1794 _kdc_free_ent(context
, client
);
1796 if (client_principal
&& client_principal
!= cp
)
1797 krb5_free_principal(context
, client_principal
);
1799 krb5_free_principal(context
, cp
);
1801 krb5_free_principal(context
, sp
);
1803 free_EncTicketPart(&adtkt
);
1813 _kdc_tgs_rep(krb5_context context
,
1814 krb5_kdc_configuration
*config
,
1818 struct sockaddr
*from_addr
,
1821 AuthorizationData
*auth_data
= NULL
;
1822 krb5_error_code ret
;
1824 const PA_DATA
*tgs_req
;
1826 hdb_entry_ex
*krbtgt
= NULL
;
1827 krb5_ticket
*ticket
= NULL
;
1828 const char *e_text
= NULL
;
1829 krb5_enctype krbtgt_etype
= ETYPE_NULL
;
1831 time_t *csec
= NULL
;
1834 if(req
->padata
== NULL
){
1835 ret
= KRB5KDC_ERR_PREAUTH_REQUIRED
; /* XXX ??? */
1836 kdc_log(context
, config
, 0,
1837 "TGS-REQ from %s without PA-DATA", from
);
1841 tgs_req
= _kdc_find_padata(req
, &i
, KRB5_PADATA_TGS_REQ
);
1843 if(tgs_req
== NULL
){
1844 ret
= KRB5KDC_ERR_PADATA_TYPE_NOSUPP
;
1846 kdc_log(context
, config
, 0,
1847 "TGS-REQ from %s without PA-TGS-REQ", from
);
1850 ret
= tgs_parse_request(context
, config
,
1851 &req
->req_body
, tgs_req
,
1860 kdc_log(context
, config
, 0,
1861 "Failed parsing TGS-REQ from %s", from
);
1865 ret
= tgs_build_reply(context
,
1879 kdc_log(context
, config
, 0,
1880 "Failed building TGS-REP to %s", from
);
1885 if (datagram_reply
&& data
->length
> config
->max_datagram_reply_length
) {
1886 krb5_data_free(data
);
1887 ret
= KRB5KRB_ERR_RESPONSE_TOO_BIG
;
1888 e_text
= "Reply packet too large";
1892 if(ret
&& data
->data
== NULL
){
1893 krb5_mk_error(context
,
1906 krb5_free_ticket(context
, ticket
);
1908 _kdc_free_ent(context
, krbtgt
);
1911 free_AuthorizationData(auth_data
);