2 * Copyright (c) 1997-2008 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
39 * return the realm of a krbtgt-ticket or NULL
43 get_krbtgt_realm(const PrincipalName
*p
)
45 if(p
->name_string
.len
== 2
46 && strcmp(p
->name_string
.val
[0], KRB5_TGS_NAME
) == 0)
47 return p
->name_string
.val
[1];
53 * The KDC might add a signed path to the ticket authorization data
54 * field. This is to avoid server impersonating clients and the
55 * request constrained delegation.
57 * This is done by storing a KRB5_AUTHDATA_IF_RELEVANT with a single
58 * entry of type KRB5SignedPath.
61 static krb5_error_code
62 find_KRB5SignedPath(krb5_context context
,
63 const AuthorizationData
*ad
,
66 AuthorizationData child
;
70 if (ad
== NULL
|| ad
->len
== 0)
71 return KRB5KDC_ERR_PADATA_TYPE_NOSUPP
;
75 if (ad
->val
[pos
].ad_type
!= KRB5_AUTHDATA_IF_RELEVANT
)
76 return KRB5KDC_ERR_PADATA_TYPE_NOSUPP
;
78 ret
= decode_AuthorizationData(ad
->val
[pos
].ad_data
.data
,
79 ad
->val
[pos
].ad_data
.length
,
83 krb5_set_error_message(context
, ret
, "Failed to decode "
84 "IF_RELEVANT with %d", ret
);
89 free_AuthorizationData(&child
);
90 return KRB5KDC_ERR_PADATA_TYPE_NOSUPP
;
93 if (child
.val
[0].ad_type
!= KRB5_AUTHDATA_SIGNTICKET
) {
94 free_AuthorizationData(&child
);
95 return KRB5KDC_ERR_PADATA_TYPE_NOSUPP
;
99 ret
= der_copy_octet_string(&child
.val
[0].ad_data
, data
);
100 free_AuthorizationData(&child
);
105 _kdc_add_KRB5SignedPath(krb5_context context
,
106 krb5_kdc_configuration
*config
,
107 hdb_entry_ex
*krbtgt
,
108 krb5_enctype enctype
,
109 krb5_principal client
,
110 krb5_const_principal server
,
111 krb5_principals principals
,
117 krb5_crypto crypto
= NULL
;
120 if (server
&& principals
) {
121 ret
= add_Principals(principals
, server
);
127 KRB5SignedPathData spd
;
130 spd
.authtime
= tkt
->authtime
;
131 spd
.delegated
= principals
;
132 spd
.method_data
= NULL
;
134 ASN1_MALLOC_ENCODE(KRB5SignedPathData
, data
.data
, data
.length
,
138 if (data
.length
!= size
)
139 krb5_abortx(context
, "internal asn.1 encoder error");
144 ret
= hdb_enctype2key(context
, &krbtgt
->entry
, enctype
, &key
);
146 ret
= krb5_crypto_init(context
, &key
->key
, 0, &crypto
);
154 * Fill in KRB5SignedPath
158 sp
.delegated
= principals
;
159 sp
.method_data
= NULL
;
161 ret
= krb5_create_checksum(context
, crypto
, KRB5_KU_KRB5SIGNEDPATH
, 0,
162 data
.data
, data
.length
, &sp
.cksum
);
163 krb5_crypto_destroy(context
, crypto
);
168 ASN1_MALLOC_ENCODE(KRB5SignedPath
, data
.data
, data
.length
, &sp
, &size
, ret
);
169 free_Checksum(&sp
.cksum
);
172 if (data
.length
!= size
)
173 krb5_abortx(context
, "internal asn.1 encoder error");
177 * Add IF-RELEVANT(KRB5SignedPath) to the last slot in
178 * authorization data field.
181 ret
= _kdc_tkt_add_if_relevant_ad(context
, tkt
,
182 KRB5_AUTHDATA_SIGNTICKET
, &data
);
183 krb5_data_free(&data
);
188 static krb5_error_code
189 check_KRB5SignedPath(krb5_context context
,
190 krb5_kdc_configuration
*config
,
191 hdb_entry_ex
*krbtgt
,
194 krb5_principals
*delegated
,
199 krb5_crypto crypto
= NULL
;
204 ret
= find_KRB5SignedPath(context
, tkt
->authorization_data
, &data
);
206 KRB5SignedPathData spd
;
210 ret
= decode_KRB5SignedPath(data
.data
, data
.length
, &sp
, NULL
);
211 krb5_data_free(&data
);
216 spd
.authtime
= tkt
->authtime
;
217 spd
.delegated
= sp
.delegated
;
218 spd
.method_data
= sp
.method_data
;
220 ASN1_MALLOC_ENCODE(KRB5SignedPathData
, data
.data
, data
.length
,
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
);
247 kdc_log(context
, config
, 5,
248 "KRB5SignedPath not signed correctly, not marking as signed");
252 if (delegated
&& sp
.delegated
) {
254 *delegated
= malloc(sizeof(*sp
.delegated
));
255 if (*delegated
== NULL
) {
256 free_KRB5SignedPath(&sp
);
260 ret
= copy_Principals(*delegated
, sp
.delegated
);
262 free_KRB5SignedPath(&sp
);
268 free_KRB5SignedPath(&sp
);
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
,
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_message(context
, ret
, "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
);
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
,
498 hdb_entry_ex
*client
,
499 krb5_const_principal server
)
501 const HDB_Ext_Constrained_delegation_acl
*acl
;
505 /* if client delegates to itself, that ok */
506 if (krb5_principal_compare(context
, client
->entry
.principal
, server
) == TRUE
)
509 if (clientdb
->hdb_check_constrained_delegation
) {
510 ret
= clientdb
->hdb_check_constrained_delegation(context
, clientdb
, client
, server
);
514 ret
= hdb_entry_get_ConstrainedDelegACL(&client
->entry
, &acl
);
516 krb5_clear_error_message(context
);
521 for (i
= 0; i
< acl
->len
; i
++) {
522 if (krb5_principal_compare(context
, server
, &acl
->val
[i
]) == TRUE
)
526 ret
= KRB5KDC_ERR_BADOPTION
;
528 kdc_log(context
, config
, 0,
529 "Bad request for constrained delegation");
537 static krb5_error_code
538 verify_flags (krb5_context context
,
539 krb5_kdc_configuration
*config
,
540 const EncTicketPart
*et
,
543 if(et
->endtime
< kdc_time
){
544 kdc_log(context
, config
, 0, "Ticket expired (%s)", pstr
);
545 return KRB5KRB_AP_ERR_TKT_EXPIRED
;
547 if(et
->flags
.invalid
){
548 kdc_log(context
, config
, 0, "Ticket not valid (%s)", pstr
);
549 return KRB5KRB_AP_ERR_TKT_NYV
;
558 static krb5_error_code
559 fix_transited_encoding(krb5_context context
,
560 krb5_kdc_configuration
*config
,
561 krb5_boolean check_policy
,
562 const TransitedEncoding
*tr
,
564 const char *client_realm
,
565 const char *server_realm
,
566 const char *tgt_realm
)
568 krb5_error_code ret
= 0;
569 char **realms
, **tmp
;
570 unsigned int num_realms
;
573 switch (tr
->tr_type
) {
574 case DOMAIN_X500_COMPRESS
:
578 * Allow empty content of type 0 because that is was Microsoft
579 * generates in their TGT.
581 if (tr
->contents
.length
== 0)
583 kdc_log(context
, config
, 0,
584 "Transited type 0 with non empty content");
585 return KRB5KDC_ERR_TRTYPE_NOSUPP
;
587 kdc_log(context
, config
, 0,
588 "Unknown transited type: %u", tr
->tr_type
);
589 return KRB5KDC_ERR_TRTYPE_NOSUPP
;
592 ret
= krb5_domain_x500_decode(context
,
599 krb5_warn(context
, ret
,
600 "Decoding transited encoding");
603 if(strcmp(client_realm
, tgt_realm
) && strcmp(server_realm
, tgt_realm
)) {
604 /* not us, so add the previous realm to transited set */
605 if (num_realms
+ 1 > UINT_MAX
/sizeof(*realms
)) {
609 tmp
= realloc(realms
, (num_realms
+ 1) * sizeof(*realms
));
615 realms
[num_realms
] = strdup(tgt_realm
);
616 if(realms
[num_realms
] == NULL
){
622 if(num_realms
== 0) {
623 if(strcmp(client_realm
, server_realm
))
624 kdc_log(context
, config
, 0,
625 "cross-realm %s -> %s", client_realm
, server_realm
);
629 for(i
= 0; i
< num_realms
; i
++)
630 l
+= strlen(realms
[i
]) + 2;
634 for(i
= 0; i
< num_realms
; i
++) {
636 strlcat(rs
, ", ", l
);
637 strlcat(rs
, realms
[i
], l
);
639 kdc_log(context
, config
, 0,
640 "cross-realm %s -> %s via [%s]",
641 client_realm
, server_realm
, rs
);
646 ret
= krb5_check_transited(context
, client_realm
,
648 realms
, num_realms
, NULL
);
650 krb5_warn(context
, ret
, "cross-realm %s -> %s",
651 client_realm
, server_realm
);
654 et
->flags
.transited_policy_checked
= 1;
656 et
->transited
.tr_type
= DOMAIN_X500_COMPRESS
;
657 ret
= krb5_domain_x500_encode(realms
, num_realms
, &et
->transited
.contents
);
659 krb5_warn(context
, ret
, "Encoding transited encoding");
661 for(i
= 0; i
< num_realms
; i
++)
668 static krb5_error_code
669 tgs_make_reply(krb5_context context
,
670 krb5_kdc_configuration
*config
,
672 krb5_const_principal tgt_name
,
673 const EncTicketPart
*tgt
,
674 const krb5_keyblock
*replykey
,
676 const EncryptionKey
*serverkey
,
677 const krb5_keyblock
*sessionkey
,
679 AuthorizationData
*auth_data
,
680 hdb_entry_ex
*server
,
681 krb5_principal server_principal
,
682 const char *server_name
,
683 hdb_entry_ex
*client
,
684 krb5_principal client_principal
,
685 hdb_entry_ex
*krbtgt
,
686 krb5_enctype krbtgt_etype
,
688 const krb5_data
*rspac
,
689 const METHOD_DATA
*enc_pa_data
,
696 KDCOptions f
= b
->kdc_options
;
700 memset(&rep
, 0, sizeof(rep
));
701 memset(&et
, 0, sizeof(et
));
702 memset(&ek
, 0, sizeof(ek
));
705 rep
.msg_type
= krb_tgs_rep
;
707 et
.authtime
= tgt
->authtime
;
708 _kdc_fix_time(&b
->till
);
709 et
.endtime
= min(tgt
->endtime
, *b
->till
);
711 *et
.starttime
= kdc_time
;
713 ret
= check_tgs_flags(context
, config
, b
, tgt
, &et
);
717 /* We should check the transited encoding if:
718 1) the request doesn't ask not to be checked
719 2) globally enforcing a check
720 3) principal requires checking
721 4) we allow non-check per-principal, but principal isn't marked as allowing this
722 5) we don't globally allow this
725 #define GLOBAL_FORCE_TRANSITED_CHECK \
726 (config->trpolicy == TRPOLICY_ALWAYS_CHECK)
727 #define GLOBAL_ALLOW_PER_PRINCIPAL \
728 (config->trpolicy == TRPOLICY_ALLOW_PER_PRINCIPAL)
729 #define GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK \
730 (config->trpolicy == TRPOLICY_ALWAYS_HONOUR_REQUEST)
732 /* these will consult the database in future release */
733 #define PRINCIPAL_FORCE_TRANSITED_CHECK(P) 0
734 #define PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(P) 0
736 ret
= fix_transited_encoding(context
, config
,
737 !f
.disable_transited_check
||
738 GLOBAL_FORCE_TRANSITED_CHECK
||
739 PRINCIPAL_FORCE_TRANSITED_CHECK(server
) ||
740 !((GLOBAL_ALLOW_PER_PRINCIPAL
&&
741 PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server
)) ||
742 GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK
),
743 &tgt
->transited
, &et
,
744 krb5_principal_get_realm(context
, client_principal
),
745 krb5_principal_get_realm(context
, server
->entry
.principal
),
746 krb5_principal_get_realm(context
, krbtgt
->entry
.principal
));
750 copy_Realm(&server_principal
->realm
, &rep
.ticket
.realm
);
751 _krb5_principal2principalname(&rep
.ticket
.sname
, server_principal
);
752 copy_Realm(&tgt_name
->realm
, &rep
.crealm
);
754 if (f.request_anonymous)
755 _kdc_make_anonymous_principalname (&rep.cname);
758 copy_PrincipalName(&tgt_name
->name
, &rep
.cname
);
759 rep
.ticket
.tkt_vno
= 5;
763 et
.caddr
= tgt
->caddr
;
767 life
= et
.endtime
- *et
.starttime
;
768 if(client
&& client
->entry
.max_life
)
769 life
= min(life
, *client
->entry
.max_life
);
770 if(server
->entry
.max_life
)
771 life
= min(life
, *server
->entry
.max_life
);
772 et
.endtime
= *et
.starttime
+ life
;
774 if(f
.renewable_ok
&& tgt
->flags
.renewable
&&
775 et
.renew_till
== NULL
&& et
.endtime
< *b
->till
){
776 et
.flags
.renewable
= 1;
777 ALLOC(et
.renew_till
);
778 *et
.renew_till
= *b
->till
;
782 renew
= *et
.renew_till
- et
.authtime
;
783 if(client
&& client
->entry
.max_renew
)
784 renew
= min(renew
, *client
->entry
.max_renew
);
785 if(server
->entry
.max_renew
)
786 renew
= min(renew
, *server
->entry
.max_renew
);
787 *et
.renew_till
= et
.authtime
+ renew
;
791 *et
.renew_till
= min(*et
.renew_till
, *tgt
->renew_till
);
792 *et
.starttime
= min(*et
.starttime
, *et
.renew_till
);
793 et
.endtime
= min(et
.endtime
, *et
.renew_till
);
796 *et
.starttime
= min(*et
.starttime
, et
.endtime
);
798 if(*et
.starttime
== et
.endtime
){
799 ret
= KRB5KDC_ERR_NEVER_VALID
;
802 if(et
.renew_till
&& et
.endtime
== *et
.renew_till
){
804 et
.renew_till
= NULL
;
805 et
.flags
.renewable
= 0;
808 et
.flags
.pre_authent
= tgt
->flags
.pre_authent
;
809 et
.flags
.hw_authent
= tgt
->flags
.hw_authent
;
810 et
.flags
.anonymous
= tgt
->flags
.anonymous
;
811 et
.flags
.ok_as_delegate
= server
->entry
.flags
.ok_as_delegate
;
815 * No not need to filter out the any PAC from the
816 * auth_data since it's signed by the KDC.
818 ret
= _kdc_tkt_add_if_relevant_ad(context
, &et
,
819 KRB5_AUTHDATA_WIN2K_PAC
, rspac
);
827 /* XXX check authdata */
829 if (et
.authorization_data
== NULL
) {
830 et
.authorization_data
= calloc(1, sizeof(*et
.authorization_data
));
831 if (et
.authorization_data
== NULL
) {
833 krb5_set_error_message(context
, ret
, "malloc: out of memory");
837 for(i
= 0; i
< auth_data
->len
; i
++) {
838 ret
= add_AuthorizationData(et
.authorization_data
, &auth_data
->val
[i
]);
840 krb5_set_error_message(context
, ret
, "malloc: out of memory");
845 /* Filter out type KRB5SignedPath */
846 ret
= find_KRB5SignedPath(context
, et
.authorization_data
, NULL
);
848 if (et
.authorization_data
->len
== 1) {
849 free_AuthorizationData(et
.authorization_data
);
850 free(et
.authorization_data
);
851 et
.authorization_data
= NULL
;
853 AuthorizationData
*ad
= et
.authorization_data
;
854 free_AuthorizationDataElement(&ad
->val
[ad
->len
- 1]);
860 ret
= krb5_copy_keyblock_contents(context
, sessionkey
, &et
.key
);
863 et
.crealm
= tgt
->crealm
;
864 et
.cname
= tgt_name
->name
;
867 /* MIT must have at least one last_req */
869 ek
.last_req
.val
= calloc(1, sizeof(*ek
.last_req
.val
));
870 if (ek
.last_req
.val
== NULL
) {
876 ek
.authtime
= et
.authtime
;
877 ek
.starttime
= et
.starttime
;
878 ek
.endtime
= et
.endtime
;
879 ek
.renew_till
= et
.renew_till
;
880 ek
.srealm
= rep
.ticket
.realm
;
881 ek
.sname
= rep
.ticket
.sname
;
883 _kdc_log_timestamp(context
, config
, "TGS-REQ", et
.authtime
, et
.starttime
,
884 et
.endtime
, et
.renew_till
);
886 /* Don't sign cross realm tickets, they can't be checked anyway */
888 char *r
= get_krbtgt_realm(&ek
.sname
);
890 if (r
== NULL
|| strcmp(r
, ek
.srealm
) == 0) {
891 ret
= _kdc_add_KRB5SignedPath(context
,
904 if (enc_pa_data
->len
) {
905 rep
.padata
= calloc(1, sizeof(*rep
.padata
));
906 if (rep
.padata
== NULL
) {
910 ret
= copy_METHOD_DATA(enc_pa_data
, rep
.padata
);
915 if (krb5_enctype_valid(context
, et
.key
.keytype
) != 0
916 && _kdc_is_weak_exception(server
->entry
.principal
, et
.key
.keytype
))
918 krb5_enctype_enable(context
, et
.key
.keytype
);
923 /* It is somewhat unclear where the etype in the following
924 encryption should come from. What we have is a session
925 key in the passed tgt, and a list of preferred etypes
926 *for the new ticket*. Should we pick the best possible
927 etype, given the keytype in the tgt, or should we look
928 at the etype list here as well? What if the tgt
929 session key is DES3 and we want a ticket with a (say)
930 CAST session key. Should the DES3 etype be added to the
931 etype list, even if we don't want a session key with
933 ret
= _kdc_encode_reply(context
, config
,
934 &rep
, &et
, &ek
, et
.key
.keytype
,
936 serverkey
, 0, replykey
, rk_is_subkey
,
939 krb5_enctype_disable(context
, et
.key
.keytype
);
943 free_TransitedEncoding(&et
.transited
);
948 if(et
.authorization_data
) {
949 free_AuthorizationData(et
.authorization_data
);
950 free(et
.authorization_data
);
952 free_LastReq(&ek
.last_req
);
953 memset(et
.key
.keyvalue
.data
, 0, et
.key
.keyvalue
.length
);
954 free_EncryptionKey(&et
.key
);
958 static krb5_error_code
959 tgs_check_authenticator(krb5_context context
,
960 krb5_kdc_configuration
*config
,
961 krb5_auth_context ac
,
966 krb5_authenticator auth
;
973 krb5_auth_con_getauthenticator(context
, ac
, &auth
);
974 if(auth
->cksum
== NULL
){
975 kdc_log(context
, config
, 0, "No authenticator in request");
976 ret
= KRB5KRB_AP_ERR_INAPP_CKSUM
;
980 * according to RFC1510 it doesn't need to be keyed,
981 * but according to the latest draft it needs to.
985 !krb5_checksum_is_keyed(context
, auth
->cksum
->cksumtype
)
988 !krb5_checksum_is_collision_proof(context
, auth
->cksum
->cksumtype
)) {
989 kdc_log(context
, config
, 0, "Bad checksum type in authenticator: %d",
990 auth
->cksum
->cksumtype
);
991 ret
= KRB5KRB_AP_ERR_INAPP_CKSUM
;
995 /* XXX should not re-encode this */
996 ASN1_MALLOC_ENCODE(KDC_REQ_BODY
, buf
, buf_size
, b
, &len
, ret
);
998 kdc_log(context
, config
, 0, "Failed to encode KDC-REQ-BODY: %s",
999 krb5_get_err_text(context
, ret
));
1002 if(buf_size
!= len
) {
1004 kdc_log(context
, config
, 0, "Internal error in ASN.1 encoder");
1005 *e_text
= "KDC internal error";
1006 ret
= KRB5KRB_ERR_GENERIC
;
1009 ret
= krb5_crypto_init(context
, key
, 0, &crypto
);
1012 kdc_log(context
, config
, 0, "krb5_crypto_init failed: %s",
1013 krb5_get_err_text(context
, ret
));
1016 ret
= krb5_verify_checksum(context
,
1018 KRB5_KU_TGS_REQ_AUTH_CKSUM
,
1023 krb5_crypto_destroy(context
, crypto
);
1025 kdc_log(context
, config
, 0,
1026 "Failed to verify authenticator checksum: %s",
1027 krb5_get_err_text(context
, ret
));
1030 free_Authenticator(auth
);
1040 find_rpath(krb5_context context
, Realm crealm
, Realm srealm
)
1042 const char *new_realm
= krb5_config_get_string(context
,
1053 need_referral(krb5_context context
, krb5_kdc_configuration
*config
,
1054 const KDCOptions
* const options
, krb5_principal server
,
1055 krb5_realm
**realms
)
1059 if(!options
->canonicalize
&& server
->name
.name_type
!= KRB5_NT_SRV_INST
)
1062 if (server
->name
.name_string
.len
== 1)
1063 name
= server
->name
.name_string
.val
[0];
1064 else if (server
->name
.name_string
.len
> 1)
1065 name
= server
->name
.name_string
.val
[1];
1069 kdc_log(context
, config
, 0, "Searching referral for %s", name
);
1071 return _krb5_get_host_realm_int(context
, name
, FALSE
, realms
) == 0;
1074 static krb5_error_code
1075 tgs_parse_request(krb5_context context
,
1076 krb5_kdc_configuration
*config
,
1078 const PA_DATA
*tgs_req
,
1079 hdb_entry_ex
**krbtgt
,
1080 krb5_enctype
*krbtgt_etype
,
1081 krb5_ticket
**ticket
,
1082 const char **e_text
,
1084 const struct sockaddr
*from_addr
,
1087 AuthorizationData
**auth_data
,
1088 krb5_keyblock
**replykey
,
1092 krb5_error_code ret
;
1093 krb5_principal princ
;
1094 krb5_auth_context ac
= NULL
;
1095 krb5_flags ap_req_options
;
1096 krb5_flags verify_ap_req_flags
;
1099 krb5_keyblock
*subkey
= NULL
;
1107 memset(&ap_req
, 0, sizeof(ap_req
));
1108 ret
= krb5_decode_ap_req(context
, &tgs_req
->padata_value
, &ap_req
);
1110 kdc_log(context
, config
, 0, "Failed to decode AP-REQ: %s",
1111 krb5_get_err_text(context
, ret
));
1115 if(!get_krbtgt_realm(&ap_req
.ticket
.sname
)){
1116 /* XXX check for ticket.sname == req.sname */
1117 kdc_log(context
, config
, 0, "PA-DATA is not a ticket-granting ticket");
1118 ret
= KRB5KDC_ERR_POLICY
; /* ? */
1122 _krb5_principalname2krb5_principal(context
,
1124 ap_req
.ticket
.sname
,
1125 ap_req
.ticket
.realm
);
1127 ret
= _kdc_db_fetch(context
, config
, princ
, HDB_F_GET_KRBTGT
, NULL
, krbtgt
);
1131 ret
= krb5_unparse_name(context
, princ
, &p
);
1133 p
= "<unparse_name failed>";
1134 krb5_free_principal(context
, princ
);
1135 kdc_log(context
, config
, 0,
1136 "Ticket-granting ticket not found in database: %s: %s",
1137 p
, krb5_get_err_text(context
, ret
));
1140 ret
= KRB5KRB_AP_ERR_NOT_US
;
1144 if(ap_req
.ticket
.enc_part
.kvno
&&
1145 *ap_req
.ticket
.enc_part
.kvno
!= (*krbtgt
)->entry
.kvno
){
1148 ret
= krb5_unparse_name (context
, princ
, &p
);
1149 krb5_free_principal(context
, princ
);
1151 p
= "<unparse_name failed>";
1152 kdc_log(context
, config
, 0,
1153 "Ticket kvno = %d, DB kvno = %d (%s)",
1154 *ap_req
.ticket
.enc_part
.kvno
,
1155 (*krbtgt
)->entry
.kvno
,
1159 ret
= KRB5KRB_AP_ERR_BADKEYVER
;
1163 *krbtgt_etype
= ap_req
.ticket
.enc_part
.etype
;
1165 ret
= hdb_enctype2key(context
, &(*krbtgt
)->entry
,
1166 ap_req
.ticket
.enc_part
.etype
, &tkey
);
1168 char *str
= NULL
, *p
= NULL
;
1170 krb5_enctype_to_string(context
, ap_req
.ticket
.enc_part
.etype
, &str
);
1171 krb5_unparse_name(context
, princ
, &p
);
1172 kdc_log(context
, config
, 0,
1173 "No server key with enctype %s found for %s",
1174 str
? str
: "<unknown enctype>",
1175 p
? p
: "<unparse_name failed>");
1178 ret
= KRB5KRB_AP_ERR_BADKEYVER
;
1182 if (b
->kdc_options
.validate
)
1183 verify_ap_req_flags
= KRB5_VERIFY_AP_REQ_IGNORE_INVALID
;
1185 verify_ap_req_flags
= 0;
1187 ret
= krb5_verify_ap_req2(context
,
1192 verify_ap_req_flags
,
1195 KRB5_KU_TGS_REQ_AUTH
);
1197 krb5_free_principal(context
, princ
);
1199 kdc_log(context
, config
, 0, "Failed to verify AP-REQ: %s",
1200 krb5_get_err_text(context
, ret
));
1205 krb5_authenticator auth
;
1207 ret
= krb5_auth_con_getauthenticator(context
, ac
, &auth
);
1209 *csec
= malloc(sizeof(**csec
));
1210 if (*csec
== NULL
) {
1211 krb5_free_authenticator(context
, &auth
);
1212 kdc_log(context
, config
, 0, "malloc failed");
1215 **csec
= auth
->ctime
;
1216 *cusec
= malloc(sizeof(**cusec
));
1217 if (*cusec
== NULL
) {
1218 krb5_free_authenticator(context
, &auth
);
1219 kdc_log(context
, config
, 0, "malloc failed");
1222 **cusec
= auth
->cusec
;
1223 krb5_free_authenticator(context
, &auth
);
1227 ret
= tgs_check_authenticator(context
, config
,
1228 ac
, b
, e_text
, &(*ticket
)->ticket
.key
);
1230 krb5_auth_con_free(context
, ac
);
1234 usage
= KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY
;
1237 ret
= krb5_auth_con_getremotesubkey(context
, ac
, &subkey
);
1239 krb5_auth_con_free(context
, ac
);
1240 kdc_log(context
, config
, 0, "Failed to get remote subkey: %s",
1241 krb5_get_err_text(context
, ret
));
1245 usage
= KRB5_KU_TGS_REQ_AUTH_DAT_SESSION
;
1248 ret
= krb5_auth_con_getkey(context
, ac
, &subkey
);
1250 krb5_auth_con_free(context
, ac
);
1251 kdc_log(context
, config
, 0, "Failed to get session key: %s",
1252 krb5_get_err_text(context
, ret
));
1257 krb5_auth_con_free(context
, ac
);
1258 kdc_log(context
, config
, 0,
1259 "Failed to get key for enc-authorization-data");
1260 ret
= KRB5KRB_AP_ERR_BAD_INTEGRITY
; /* ? */
1266 if (b
->enc_authorization_data
) {
1269 ret
= krb5_crypto_init(context
, subkey
, 0, &crypto
);
1271 krb5_auth_con_free(context
, ac
);
1272 kdc_log(context
, config
, 0, "krb5_crypto_init failed: %s",
1273 krb5_get_err_text(context
, ret
));
1276 ret
= krb5_decrypt_EncryptedData (context
,
1279 b
->enc_authorization_data
,
1281 krb5_crypto_destroy(context
, crypto
);
1283 krb5_auth_con_free(context
, ac
);
1284 kdc_log(context
, config
, 0,
1285 "Failed to decrypt enc-authorization-data");
1286 ret
= KRB5KRB_AP_ERR_BAD_INTEGRITY
; /* ? */
1290 if (*auth_data
== NULL
) {
1291 krb5_auth_con_free(context
, ac
);
1292 ret
= KRB5KRB_AP_ERR_BAD_INTEGRITY
; /* ? */
1295 ret
= decode_AuthorizationData(ad
.data
, ad
.length
, *auth_data
, NULL
);
1297 krb5_auth_con_free(context
, ac
);
1300 kdc_log(context
, config
, 0, "Failed to decode authorization data");
1301 ret
= KRB5KRB_AP_ERR_BAD_INTEGRITY
; /* ? */
1306 krb5_auth_con_free(context
, ac
);
1309 free_AP_REQ(&ap_req
);
1314 static krb5_error_code
1315 build_server_referral(krb5_context context
,
1316 krb5_kdc_configuration
*config
,
1317 krb5_crypto session
,
1318 krb5_const_realm referred_realm
,
1319 const PrincipalName
*true_principal_name
,
1320 const PrincipalName
*requested_principal
,
1323 PA_ServerReferralData ref
;
1324 krb5_error_code ret
;
1329 memset(&ref
, 0, sizeof(ref
));
1331 if (referred_realm
) {
1332 ALLOC(ref
.referred_realm
);
1333 if (ref
.referred_realm
== NULL
)
1335 *ref
.referred_realm
= strdup(referred_realm
);
1336 if (*ref
.referred_realm
== NULL
)
1339 if (true_principal_name
) {
1340 ALLOC(ref
.true_principal_name
);
1341 if (ref
.true_principal_name
== NULL
)
1343 ret
= copy_PrincipalName(true_principal_name
, ref
.true_principal_name
);
1347 if (requested_principal
) {
1348 ALLOC(ref
.requested_principal_name
);
1349 if (ref
.requested_principal_name
== NULL
)
1351 ret
= copy_PrincipalName(requested_principal
,
1352 ref
.requested_principal_name
);
1357 ASN1_MALLOC_ENCODE(PA_ServerReferralData
,
1358 data
.data
, data
.length
,
1360 free_PA_ServerReferralData(&ref
);
1363 if (data
.length
!= size
)
1364 krb5_abortx(context
, "internal asn.1 encoder error");
1366 ret
= krb5_encrypt_EncryptedData(context
, session
,
1367 KRB5_KU_PA_SERVER_REFERRAL
,
1368 data
.data
, data
.length
,
1374 ASN1_MALLOC_ENCODE(EncryptedData
,
1375 outdata
->data
, outdata
->length
,
1377 free_EncryptedData(&ed
);
1380 if (outdata
->length
!= size
)
1381 krb5_abortx(context
, "internal asn.1 encoder error");
1385 free_PA_ServerReferralData(&ref
);
1386 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
1390 static krb5_error_code
1391 tgs_build_reply(krb5_context context
,
1392 krb5_kdc_configuration
*config
,
1395 hdb_entry_ex
*krbtgt
,
1396 krb5_enctype krbtgt_etype
,
1397 const krb5_keyblock
*replykey
,
1399 krb5_ticket
*ticket
,
1402 const char **e_text
,
1403 AuthorizationData
**auth_data
,
1404 const struct sockaddr
*from_addr
)
1406 krb5_error_code ret
;
1407 krb5_principal cp
= NULL
, sp
= NULL
;
1408 krb5_principal client_principal
= NULL
;
1409 char *spn
= NULL
, *cpn
= NULL
;
1410 hdb_entry_ex
*server
= NULL
, *client
= NULL
;
1412 krb5_realm ref_realm
= NULL
;
1413 EncTicketPart
*tgt
= &ticket
->ticket
;
1414 krb5_principals spp
= NULL
;
1415 const EncryptionKey
*ekey
;
1416 krb5_keyblock sessionkey
;
1420 METHOD_DATA enc_pa_data
;
1425 EncTicketPart adtkt
;
1431 memset(&sessionkey
, 0, sizeof(sessionkey
));
1432 memset(&adtkt
, 0, sizeof(adtkt
));
1433 krb5_data_zero(&rspac
);
1434 memset(&enc_pa_data
, 0, sizeof(enc_pa_data
));
1439 if(b
->kdc_options
.enc_tkt_in_skey
){
1445 if(b
->additional_tickets
== NULL
||
1446 b
->additional_tickets
->len
== 0){
1447 ret
= KRB5KDC_ERR_BADOPTION
; /* ? */
1448 kdc_log(context
, config
, 0,
1449 "No second ticket present in request");
1452 t
= &b
->additional_tickets
->val
[0];
1453 if(!get_krbtgt_realm(&t
->sname
)){
1454 kdc_log(context
, config
, 0,
1455 "Additional ticket is not a ticket-granting ticket");
1456 ret
= KRB5KDC_ERR_POLICY
;
1459 _krb5_principalname2krb5_principal(context
, &p
, t
->sname
, t
->realm
);
1460 ret
= _kdc_db_fetch(context
, config
, p
,
1461 HDB_F_GET_CLIENT
|HDB_F_GET_SERVER
,
1463 krb5_free_principal(context
, p
);
1465 if (ret
== HDB_ERR_NOENTRY
)
1466 ret
= KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
;
1469 ret
= hdb_enctype2key(context
, &uu
->entry
,
1470 t
->enc_part
.etype
, &uukey
);
1472 _kdc_free_ent(context
, uu
);
1473 ret
= KRB5KDC_ERR_ETYPE_NOSUPP
; /* XXX */
1476 ret
= krb5_decrypt_ticket(context
, t
, &uukey
->key
, &adtkt
, 0);
1477 _kdc_free_ent(context
, uu
);
1481 ret
= verify_flags(context
, config
, &adtkt
, spn
);
1489 _krb5_principalname2krb5_principal(context
, &sp
, *s
, r
);
1490 ret
= krb5_unparse_name(context
, sp
, &spn
);
1493 _krb5_principalname2krb5_principal(context
, &cp
, tgt
->cname
, tgt
->crealm
);
1494 ret
= krb5_unparse_name(context
, cp
, &cpn
);
1497 unparse_flags (KDCOptions2int(b
->kdc_options
),
1498 asn1_KDCOptions_units(),
1499 opt_str
, sizeof(opt_str
));
1501 kdc_log(context
, config
, 0,
1502 "TGS-REQ %s from %s for %s [%s]",
1503 cpn
, from
, spn
, opt_str
);
1505 kdc_log(context
, config
, 0,
1506 "TGS-REQ %s from %s for %s", cpn
, from
, spn
);
1513 ret
= _kdc_db_fetch(context
, config
, sp
, HDB_F_GET_SERVER
| HDB_F_CANON
,
1517 const char *new_rlm
;
1521 if ((req_rlm
= get_krbtgt_realm(&sp
->name
)) != NULL
) {
1523 new_rlm
= find_rpath(context
, tgt
->crealm
, req_rlm
);
1525 kdc_log(context
, config
, 5, "krbtgt for realm %s "
1526 "not found, trying %s",
1528 krb5_free_principal(context
, sp
);
1530 krb5_make_principal(context
, &sp
, r
,
1531 KRB5_TGS_NAME
, new_rlm
, NULL
);
1532 ret
= krb5_unparse_name(context
, sp
, &spn
);
1538 ref_realm
= strdup(new_rlm
);
1542 } else if(need_referral(context
, config
, &b
->kdc_options
, sp
, &realms
)) {
1543 if (strcmp(realms
[0], sp
->realm
) != 0) {
1544 kdc_log(context
, config
, 5,
1545 "Returning a referral to realm %s for "
1546 "server %s that was not found",
1548 krb5_free_principal(context
, sp
);
1550 krb5_make_principal(context
, &sp
, r
, KRB5_TGS_NAME
,
1552 ret
= krb5_unparse_name(context
, sp
, &spn
);
1558 ref_realm
= strdup(realms
[0]);
1560 krb5_free_host_realm(context
, realms
);
1563 krb5_free_host_realm(context
, realms
);
1565 kdc_log(context
, config
, 0,
1566 "Server not found in database: %s: %s", spn
,
1567 krb5_get_err_text(context
, ret
));
1568 if (ret
== HDB_ERR_NOENTRY
)
1569 ret
= KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
;
1573 ret
= _kdc_db_fetch(context
, config
, cp
, HDB_F_GET_CLIENT
| HDB_F_CANON
,
1574 &clientdb
, &client
);
1576 const char *krbtgt_realm
;
1579 * If the client belongs to the same realm as our krbtgt, it
1580 * should exist in the local database.
1585 krb5_principal_get_comp_string(context
,
1586 krbtgt
->entry
.principal
, 1);
1588 if(strcmp(krb5_principal_get_realm(context
, cp
), krbtgt_realm
) == 0) {
1589 if (ret
== HDB_ERR_NOENTRY
)
1590 ret
= KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN
;
1591 kdc_log(context
, config
, 1, "Client no longer in database: %s",
1596 kdc_log(context
, config
, 1, "Client not found in database: %s: %s",
1597 cpn
, krb5_get_err_text(context
, ret
));
1601 * Select enctype, return key and kvno.
1607 if(b
->kdc_options
.enc_tkt_in_skey
) {
1610 for(i
= 0; i
< b
->etype
.len
; i
++)
1611 if (b
->etype
.val
[i
] == adtkt
.key
.keytype
)
1613 if(i
== b
->etype
.len
) {
1614 kdc_log(context
, config
, 0,
1615 "Addition ticket have not matching etypes");
1616 krb5_clear_error_message(context
);
1617 ret
= KRB5KDC_ERR_ETYPE_NOSUPP
;
1620 etype
= b
->etype
.val
[i
];
1625 ret
= _kdc_find_etype(context
, server
, b
->etype
.val
, b
->etype
.len
,
1628 kdc_log(context
, config
, 0,
1629 "Server (%s) has no support for etypes", spn
);
1633 kvno
= server
->entry
.kvno
;
1636 ret
= krb5_generate_random_keyblock(context
, etype
, &sessionkey
);
1642 * Check that service is in the same realm as the krbtgt. If it's
1643 * not the same, it's someone that is using a uni-directional trust
1647 if (strcmp(krb5_principal_get_realm(context
, sp
),
1648 krb5_principal_get_comp_string(context
,
1649 krbtgt
->entry
.principal
,
1652 ret
= krb5_unparse_name(context
, krbtgt
->entry
.principal
, &tpn
);
1653 kdc_log(context
, config
, 0,
1654 "Request with wrong krbtgt: %s",
1655 (ret
== 0) ? tpn
: "<unknown>");
1658 ret
= KRB5KRB_AP_ERR_NOT_US
;
1663 * Validate authoriation data
1666 ret
= hdb_enctype2key(context
, &krbtgt
->entry
,
1667 krbtgt_etype
, &tkey
);
1669 kdc_log(context
, config
, 0,
1670 "Failed to find key for krbtgt PAC check");
1674 ret
= check_PAC(context
, config
, cp
,
1675 client
, server
, ekey
, &tkey
->key
,
1676 tgt
, &rspac
, &signedpath
);
1678 kdc_log(context
, config
, 0,
1679 "Verify PAC failed for %s (%s) from %s with %s",
1680 spn
, cpn
, from
, krb5_get_err_text(context
, ret
));
1684 /* also check the krbtgt for signature */
1685 ret
= check_KRB5SignedPath(context
,
1693 kdc_log(context
, config
, 0,
1694 "KRB5SignedPath check failed for %s (%s) from %s with %s",
1695 spn
, cpn
, from
, krb5_get_err_text(context
, ret
));
1703 client_principal
= cp
;
1706 const PA_DATA
*sdata
;
1709 sdata
= _kdc_find_padata(req
, &i
, KRB5_PADATA_FOR_USER
);
1714 char *selfcpn
= NULL
;
1717 ret
= decode_PA_S4U2Self(sdata
->padata_value
.data
,
1718 sdata
->padata_value
.length
,
1721 kdc_log(context
, config
, 0, "Failed to decode PA-S4U2Self");
1725 ret
= _krb5_s4u2self_to_checksumdata(context
, &self
, &datack
);
1729 ret
= krb5_crypto_init(context
, &tgt
->key
, 0, &crypto
);
1731 free_PA_S4U2Self(&self
);
1732 krb5_data_free(&datack
);
1733 kdc_log(context
, config
, 0, "krb5_crypto_init failed: %s",
1734 krb5_get_err_text(context
, ret
));
1738 ret
= krb5_verify_checksum(context
,
1740 KRB5_KU_OTHER_CKSUM
,
1744 krb5_data_free(&datack
);
1745 krb5_crypto_destroy(context
, crypto
);
1747 free_PA_S4U2Self(&self
);
1748 kdc_log(context
, config
, 0,
1749 "krb5_verify_checksum failed for S4U2Self: %s",
1750 krb5_get_err_text(context
, ret
));
1754 ret
= _krb5_principalname2krb5_principal(context
,
1758 free_PA_S4U2Self(&self
);
1762 ret
= krb5_unparse_name(context
, client_principal
, &selfcpn
);
1767 * Check that service doing the impersonating is
1768 * requesting a ticket to it-self.
1770 if (krb5_principal_compare(context
, cp
, sp
) != TRUE
) {
1771 kdc_log(context
, config
, 0, "S4U2Self: %s is not allowed "
1772 "to impersonate some other user "
1773 "(tried for user %s to service %s)",
1776 ret
= KRB5KDC_ERR_BADOPTION
; /* ? */
1781 * If the service isn't trusted for authentication to
1782 * delegation, remove the forward flag.
1785 if (client
->entry
.flags
.trusted_for_delegation
) {
1786 str
= "[forwardable]";
1788 b
->kdc_options
.forwardable
= 0;
1791 kdc_log(context
, config
, 0, "s4u2self %s impersonating %s to "
1792 "service %s %s", cpn
, selfcpn
, spn
, str
);
1798 * Constrained delegation
1802 && b
->additional_tickets
!= NULL
1803 && b
->additional_tickets
->len
!= 0
1804 && b
->kdc_options
.enc_tkt_in_skey
== 0)
1806 int ad_signedpath
= 0;
1812 * Require that the KDC have issued the service's krbtgt (not
1813 * self-issued ticket with kimpersonate(1).
1816 ret
= KRB5KDC_ERR_BADOPTION
;
1817 kdc_log(context
, config
, 0,
1818 "Constrained delegation done on service ticket %s/%s",
1823 t
= &b
->additional_tickets
->val
[0];
1825 ret
= hdb_enctype2key(context
, &client
->entry
,
1826 t
->enc_part
.etype
, &clientkey
);
1828 ret
= KRB5KDC_ERR_ETYPE_NOSUPP
; /* XXX */
1832 ret
= krb5_decrypt_ticket(context
, t
, &clientkey
->key
, &adtkt
, 0);
1834 kdc_log(context
, config
, 0,
1835 "failed to decrypt ticket for "
1836 "constrained delegation from %s to %s ", cpn
, spn
);
1840 /* check that ticket is valid */
1841 if (adtkt
.flags
.forwardable
== 0) {
1842 kdc_log(context
, config
, 0,
1843 "Missing forwardable flag on ticket for "
1844 "constrained delegation from %s to %s ", cpn
, spn
);
1845 ret
= KRB5KDC_ERR_BADOPTION
;
1849 ret
= check_constrained_delegation(context
, config
, clientdb
,
1852 kdc_log(context
, config
, 0,
1853 "constrained delegation from %s to %s not allowed",
1858 ret
= _krb5_principalname2krb5_principal(context
,
1865 ret
= krb5_unparse_name(context
, client_principal
, &str
);
1869 ret
= verify_flags(context
, config
, &adtkt
, str
);
1876 * Check that the KDC issued the user's ticket.
1878 ret
= check_KRB5SignedPath(context
,
1885 if (ret
== 0 && !ad_signedpath
)
1886 ret
= KRB5KDC_ERR_BADOPTION
;
1888 kdc_log(context
, config
, 0,
1889 "KRB5SignedPath check from service %s failed "
1890 "for delegation to %s for client %s "
1891 "from %s failed with %s",
1892 spn
, str
, cpn
, from
, krb5_get_err_text(context
, ret
));
1897 kdc_log(context
, config
, 0, "constrained delegation for %s "
1898 "from %s to %s", str
, cpn
, spn
);
1906 ret
= kdc_check_flags(context
, config
,
1913 if((b
->kdc_options
.validate
|| b
->kdc_options
.renew
) &&
1914 !krb5_principal_compare(context
,
1915 krbtgt
->entry
.principal
,
1916 server
->entry
.principal
)){
1917 kdc_log(context
, config
, 0, "Inconsistent request.");
1918 ret
= KRB5KDC_ERR_SERVER_NOMATCH
;
1922 /* check for valid set of addresses */
1923 if(!_kdc_check_addresses(context
, config
, tgt
->caddr
, from_addr
)) {
1924 ret
= KRB5KRB_AP_ERR_BADADDR
;
1925 kdc_log(context
, config
, 0, "Request from wrong address");
1930 * If this is an referral, add server referral data to the
1937 kdc_log(context
, config
, 0,
1938 "Adding server referral to %s", ref_realm
);
1940 ret
= krb5_crypto_init(context
, &sessionkey
, 0, &crypto
);
1944 ret
= build_server_referral(context
, config
, crypto
, ref_realm
,
1945 NULL
, s
, &pa
.padata_value
);
1946 krb5_crypto_destroy(context
, crypto
);
1948 kdc_log(context
, config
, 0,
1949 "Failed building server referral");
1952 pa
.padata_type
= KRB5_PADATA_SERVER_REFERRAL
;
1954 ret
= add_METHOD_DATA(&enc_pa_data
, &pa
);
1955 krb5_data_free(&pa
.padata_value
);
1957 kdc_log(context
, config
, 0,
1958 "Add server referral METHOD-DATA failed");
1967 ret
= tgs_make_reply(context
,
1995 krb5_data_free(&rspac
);
1996 krb5_free_keyblock_contents(context
, &sessionkey
);
1998 _kdc_free_ent(context
, server
);
2000 _kdc_free_ent(context
, client
);
2002 if (client_principal
&& client_principal
!= cp
)
2003 krb5_free_principal(context
, client_principal
);
2005 krb5_free_principal(context
, cp
);
2007 krb5_free_principal(context
, sp
);
2010 free_METHOD_DATA(&enc_pa_data
);
2012 free_EncTicketPart(&adtkt
);
2022 _kdc_tgs_rep(krb5_context context
,
2023 krb5_kdc_configuration
*config
,
2027 struct sockaddr
*from_addr
,
2030 AuthorizationData
*auth_data
= NULL
;
2031 krb5_error_code ret
;
2033 const PA_DATA
*tgs_req
;
2035 hdb_entry_ex
*krbtgt
= NULL
;
2036 krb5_ticket
*ticket
= NULL
;
2037 const char *e_text
= NULL
;
2038 krb5_enctype krbtgt_etype
= ETYPE_NULL
;
2040 krb5_keyblock
*replykey
= NULL
;
2041 int rk_is_subkey
= 0;
2042 time_t *csec
= NULL
;
2045 if(req
->padata
== NULL
){
2046 ret
= KRB5KDC_ERR_PREAUTH_REQUIRED
; /* XXX ??? */
2047 kdc_log(context
, config
, 0,
2048 "TGS-REQ from %s without PA-DATA", from
);
2052 tgs_req
= _kdc_find_padata(req
, &i
, KRB5_PADATA_TGS_REQ
);
2054 if(tgs_req
== NULL
){
2055 ret
= KRB5KDC_ERR_PADATA_TYPE_NOSUPP
;
2057 kdc_log(context
, config
, 0,
2058 "TGS-REQ from %s without PA-TGS-REQ", from
);
2061 ret
= tgs_parse_request(context
, config
,
2062 &req
->req_body
, tgs_req
,
2073 kdc_log(context
, config
, 0,
2074 "Failed parsing TGS-REQ from %s", from
);
2078 ret
= tgs_build_reply(context
,
2093 kdc_log(context
, config
, 0,
2094 "Failed building TGS-REP to %s", from
);
2099 if (datagram_reply
&& data
->length
> config
->max_datagram_reply_length
) {
2100 krb5_data_free(data
);
2101 ret
= KRB5KRB_ERR_RESPONSE_TOO_BIG
;
2102 e_text
= "Reply packet too large";
2107 krb5_free_keyblock(context
, replykey
);
2108 if(ret
&& data
->data
== NULL
){
2109 krb5_mk_error(context
,
2122 krb5_free_ticket(context
, ticket
);
2124 _kdc_free_ent(context
, krbtgt
);
2127 free_AuthorizationData(auth_data
);