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_const_principal server,
110 KRB5SignedPathPrincipals *principals,
116 krb5_crypto crypto = NULL;
119 if (server && principals) {
120 ret = add_KRB5SignedPathPrincipals(principals, server);
126 KRB5SignedPathData spd;
128 spd.encticket = *tkt;
129 spd.delegated = principals;
131 ASN1_MALLOC_ENCODE(KRB5SignedPathData, data.data, data.length,
135 if (data.length != size)
136 krb5_abortx(context, "internal asn.1 encoder error");
141 ret = hdb_enctype2key(context, &krbtgt->entry, enctype, &key);
143 ret = krb5_crypto_init(context, &key->key, 0, &crypto);
151 * Fill in KRB5SignedPath
155 sp.delegated = principals;
157 ret = krb5_create_checksum(context, crypto, KRB5_KU_KRB5SIGNEDPATH, 0,
158 data.data, data.length, &sp.cksum);
159 krb5_crypto_destroy(context, crypto);
164 ASN1_MALLOC_ENCODE(KRB5SignedPath, data.data, data.length, &sp, &size, ret);
165 free_Checksum(&sp.cksum);
168 if (data.length != size)
169 krb5_abortx(context, "internal asn.1 encoder error");
173 * Add IF-RELEVANT(KRB5SignedPath) to the last slot in
174 * authorization data field.
177 ret = _kdc_tkt_add_if_relevant_ad(context, tkt,
178 KRB5_AUTHDATA_SIGNTICKET, &data);
179 krb5_data_free(&data);
184 static krb5_error_code
185 check_KRB5SignedPath(krb5_context context,
186 krb5_kdc_configuration *config,
187 hdb_entry_ex *krbtgt,
189 KRB5SignedPathPrincipals **delegated,
194 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);
250 if (delegated && sp.delegated) {
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);
278 static krb5_error_code
279 check_PAC(krb5_context context,
280 krb5_kdc_configuration *config,
281 const krb5_principal client_principal,
282 hdb_entry_ex *client,
283 hdb_entry_ex *server,
284 const EncryptionKey *server_key,
285 const EncryptionKey *krbtgt_key,
290 AuthorizationData *ad = tkt->authorization_data;
294 if (ad == NULL || ad->len == 0)
297 for (i = 0; i < ad->len; i++) {
298 AuthorizationData child;
300 if (ad->val[i].ad_type != KRB5_AUTHDATA_IF_RELEVANT)
303 ret = decode_AuthorizationData(ad->val[i].ad_data.data,
304 ad->val[i].ad_data.length,
308 krb5_set_error_message(context, ret, "Failed to decode "
309 "IF_RELEVANT with %d", ret);
312 for (j = 0; j < child.len; j++) {
314 if (child.val[j].ad_type == KRB5_AUTHDATA_WIN2K_PAC) {
318 ret = krb5_pac_parse(context,
319 child.val[j].ad_data.data,
320 child.val[j].ad_data.length,
322 free_AuthorizationData(&child);
326 ret = krb5_pac_verify(context, pac, tkt->authtime,
330 krb5_pac_free(context, pac);
334 ret = _kdc_pac_verify(context, client_principal,
335 client, server, &pac);
337 krb5_pac_free(context, pac);
342 ret = _krb5_pac_sign(context, pac, tkt->authtime,
344 server_key, krbtgt_key, rspac);
346 krb5_pac_free(context, pac);
351 free_AuthorizationData(&child);
360 static krb5_error_code
361 check_tgs_flags(krb5_context context,
362 krb5_kdc_configuration *config,
363 KDC_REQ_BODY *b, const EncTicketPart *tgt, EncTicketPart *et)
365 KDCOptions f = b->kdc_options;
368 if(!tgt->flags.invalid || tgt->starttime == NULL){
369 kdc_log(context, config, 0,
370 "Bad request to validate ticket");
371 return KRB5KDC_ERR_BADOPTION;
373 if(*tgt->starttime > kdc_time){
374 kdc_log(context, config, 0,
375 "Early request to validate ticket");
376 return KRB5KRB_AP_ERR_TKT_NYV;
379 et->flags.invalid = 0;
380 }else if(tgt->flags.invalid){
381 kdc_log(context, config, 0,
382 "Ticket-granting ticket has INVALID flag set");
383 return KRB5KRB_AP_ERR_TKT_INVALID;
387 if(!tgt->flags.forwardable){
388 kdc_log(context, config, 0,
389 "Bad request for forwardable ticket");
390 return KRB5KDC_ERR_BADOPTION;
392 et->flags.forwardable = 1;
395 if(!tgt->flags.forwardable){
396 kdc_log(context, config, 0,
397 "Request to forward non-forwardable ticket");
398 return KRB5KDC_ERR_BADOPTION;
400 et->flags.forwarded = 1;
401 et->caddr = b->addresses;
403 if(tgt->flags.forwarded)
404 et->flags.forwarded = 1;
407 if(!tgt->flags.proxiable){
408 kdc_log(context, config, 0,
409 "Bad request for proxiable ticket");
410 return KRB5KDC_ERR_BADOPTION;
412 et->flags.proxiable = 1;
415 if(!tgt->flags.proxiable){
416 kdc_log(context, config, 0,
417 "Request to proxy non-proxiable ticket");
418 return KRB5KDC_ERR_BADOPTION;
421 et->caddr = b->addresses;
426 if(f.allow_postdate){
427 if(!tgt->flags.may_postdate){
428 kdc_log(context, config, 0,
429 "Bad request for post-datable ticket");
430 return KRB5KDC_ERR_BADOPTION;
432 et->flags.may_postdate = 1;
435 if(!tgt->flags.may_postdate){
436 kdc_log(context, config, 0,
437 "Bad request for postdated ticket");
438 return KRB5KDC_ERR_BADOPTION;
441 *et->starttime = *b->from;
442 et->flags.postdated = 1;
443 et->flags.invalid = 1;
444 }else if(b->from && *b->from > kdc_time + context->max_skew){
445 kdc_log(context, config, 0, "Ticket cannot be postdated");
446 return KRB5KDC_ERR_CANNOT_POSTDATE;
450 if(!tgt->flags.renewable){
451 kdc_log(context, config, 0,
452 "Bad request for renewable ticket");
453 return KRB5KDC_ERR_BADOPTION;
455 et->flags.renewable = 1;
456 ALLOC(et->renew_till);
457 _kdc_fix_time(&b->rtime);
458 *et->renew_till = *b->rtime;
462 if(!tgt->flags.renewable || tgt->renew_till == NULL){
463 kdc_log(context, config, 0,
464 "Request to renew non-renewable ticket");
465 return KRB5KDC_ERR_BADOPTION;
467 old_life = tgt->endtime;
469 old_life -= *tgt->starttime;
471 old_life -= tgt->authtime;
472 et->endtime = *et->starttime + old_life;
473 if (et->renew_till != NULL)
474 et->endtime = min(*et->renew_till, et->endtime);
478 /* checks for excess flags */
479 if(f.request_anonymous && !config->allow_anonymous){
480 kdc_log(context, config, 0,
481 "Request for anonymous ticket");
482 return KRB5KDC_ERR_BADOPTION;
492 static krb5_error_code
493 check_constrained_delegation(krb5_context context,
494 krb5_kdc_configuration *config,
495 hdb_entry_ex *client,
496 krb5_const_principal server)
498 const HDB_Ext_Constrained_delegation_acl *acl;
502 ret = hdb_entry_get_ConstrainedDelegACL(&client->entry, &acl);
504 krb5_clear_error_string(context);
509 for (i = 0; i < acl->len; i++) {
510 if (krb5_principal_compare(context, server, &acl->val[i]) == TRUE)
514 kdc_log(context, config, 0,
515 "Bad request for constrained delegation");
516 return KRB5KDC_ERR_BADOPTION;
523 static krb5_error_code
524 verify_flags (krb5_context context,
525 krb5_kdc_configuration *config,
526 const EncTicketPart *et,
529 if(et->endtime < kdc_time){
530 kdc_log(context, config, 0, "Ticket expired (%s)", pstr);
531 return KRB5KRB_AP_ERR_TKT_EXPIRED;
533 if(et->flags.invalid){
534 kdc_log(context, config, 0, "Ticket not valid (%s)", pstr);
535 return KRB5KRB_AP_ERR_TKT_NYV;
544 static krb5_error_code
545 fix_transited_encoding(krb5_context context,
546 krb5_kdc_configuration *config,
547 krb5_boolean check_policy,
548 const TransitedEncoding *tr,
550 const char *client_realm,
551 const char *server_realm,
552 const char *tgt_realm)
554 krb5_error_code ret = 0;
555 char **realms, **tmp;
556 unsigned int num_realms;
559 switch (tr->tr_type) {
560 case DOMAIN_X500_COMPRESS:
564 * Allow empty content of type 0 because that is was Microsoft
565 * generates in their TGT.
567 if (tr->contents.length == 0)
569 kdc_log(context, config, 0,
570 "Transited type 0 with non empty content");
571 return KRB5KDC_ERR_TRTYPE_NOSUPP;
573 kdc_log(context, config, 0,
574 "Unknown transited type: %u", tr->tr_type);
575 return KRB5KDC_ERR_TRTYPE_NOSUPP;
578 ret = krb5_domain_x500_decode(context,
585 krb5_warn(context, ret,
586 "Decoding transited encoding");
589 if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) {
590 /* not us, so add the previous realm to transited set */
591 if (num_realms + 1 > UINT_MAX/sizeof(*realms)) {
595 tmp = realloc(realms, (num_realms + 1) * sizeof(*realms));
601 realms[num_realms] = strdup(tgt_realm);
602 if(realms[num_realms] == NULL){
608 if(num_realms == 0) {
609 if(strcmp(client_realm, server_realm))
610 kdc_log(context, config, 0,
611 "cross-realm %s -> %s", client_realm, server_realm);
615 for(i = 0; i < num_realms; i++)
616 l += strlen(realms[i]) + 2;
620 for(i = 0; i < num_realms; i++) {
622 strlcat(rs, ", ", l);
623 strlcat(rs, realms[i], l);
625 kdc_log(context, config, 0,
626 "cross-realm %s -> %s via [%s]",
627 client_realm, server_realm, rs);
632 ret = krb5_check_transited(context, client_realm,
634 realms, num_realms, NULL);
636 krb5_warn(context, ret, "cross-realm %s -> %s",
637 client_realm, server_realm);
640 et->flags.transited_policy_checked = 1;
642 et->transited.tr_type = DOMAIN_X500_COMPRESS;
643 ret = krb5_domain_x500_encode(realms, num_realms, &et->transited.contents);
645 krb5_warn(context, ret, "Encoding transited encoding");
647 for(i = 0; i < num_realms; i++)
654 static krb5_error_code
655 tgs_make_reply(krb5_context context,
656 krb5_kdc_configuration *config,
658 krb5_const_principal tgt_name,
659 const EncTicketPart *tgt,
660 const EncryptionKey *serverkey,
661 const krb5_keyblock *sessionkey,
663 AuthorizationData *auth_data,
664 hdb_entry_ex *server,
665 krb5_principal server_principal,
666 const char *server_name,
667 hdb_entry_ex *client,
668 krb5_principal client_principal,
669 hdb_entry_ex *krbtgt,
670 krb5_enctype krbtgt_etype,
671 KRB5SignedPathPrincipals *spp,
672 const krb5_data *rspac,
673 const METHOD_DATA *enc_pa_data,
680 KDCOptions f = b->kdc_options;
684 memset(&rep, 0, sizeof(rep));
685 memset(&et, 0, sizeof(et));
686 memset(&ek, 0, sizeof(ek));
689 rep.msg_type = krb_tgs_rep;
691 et.authtime = tgt->authtime;
692 _kdc_fix_time(&b->till);
693 et.endtime = min(tgt->endtime, *b->till);
695 *et.starttime = kdc_time;
697 ret = check_tgs_flags(context, config, b, tgt, &et);
701 /* We should check the transited encoding if:
702 1) the request doesn't ask not to be checked
703 2) globally enforcing a check
704 3) principal requires checking
705 4) we allow non-check per-principal, but principal isn't marked as allowing this
706 5) we don't globally allow this
709 #define GLOBAL_FORCE_TRANSITED_CHECK \
710 (config->trpolicy == TRPOLICY_ALWAYS_CHECK)
711 #define GLOBAL_ALLOW_PER_PRINCIPAL \
712 (config->trpolicy == TRPOLICY_ALLOW_PER_PRINCIPAL)
713 #define GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK \
714 (config->trpolicy == TRPOLICY_ALWAYS_HONOUR_REQUEST)
716 /* these will consult the database in future release */
717 #define PRINCIPAL_FORCE_TRANSITED_CHECK(P) 0
718 #define PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(P) 0
720 ret = fix_transited_encoding(context, config,
721 !f.disable_transited_check ||
722 GLOBAL_FORCE_TRANSITED_CHECK ||
723 PRINCIPAL_FORCE_TRANSITED_CHECK(server) ||
724 !((GLOBAL_ALLOW_PER_PRINCIPAL &&
725 PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server)) ||
726 GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK),
727 &tgt->transited, &et,
728 *krb5_princ_realm(context, client_principal),
729 *krb5_princ_realm(context, server->entry.principal),
730 *krb5_princ_realm(context, krbtgt->entry.principal));
734 copy_Realm(krb5_princ_realm(context, server_principal),
736 _krb5_principal2principalname(&rep.ticket.sname, server_principal);
737 copy_Realm(&tgt_name->realm, &rep.crealm);
739 if (f.request_anonymous)
740 _kdc_make_anonymous_principalname (&rep.cname);
743 copy_PrincipalName(&tgt_name->name, &rep.cname);
744 rep.ticket.tkt_vno = 5;
748 et.caddr = tgt->caddr;
752 life = et.endtime - *et.starttime;
753 if(client && client->entry.max_life)
754 life = min(life, *client->entry.max_life);
755 if(server->entry.max_life)
756 life = min(life, *server->entry.max_life);
757 et.endtime = *et.starttime + life;
759 if(f.renewable_ok && tgt->flags.renewable &&
760 et.renew_till == NULL && et.endtime < *b->till){
761 et.flags.renewable = 1;
762 ALLOC(et.renew_till);
763 *et.renew_till = *b->till;
767 renew = *et.renew_till - et.authtime;
768 if(client && client->entry.max_renew)
769 renew = min(renew, *client->entry.max_renew);
770 if(server->entry.max_renew)
771 renew = min(renew, *server->entry.max_renew);
772 *et.renew_till = et.authtime + renew;
776 *et.renew_till = min(*et.renew_till, *tgt->renew_till);
777 *et.starttime = min(*et.starttime, *et.renew_till);
778 et.endtime = min(et.endtime, *et.renew_till);
781 *et.starttime = min(*et.starttime, et.endtime);
783 if(*et.starttime == et.endtime){
784 ret = KRB5KDC_ERR_NEVER_VALID;
787 if(et.renew_till && et.endtime == *et.renew_till){
789 et.renew_till = NULL;
790 et.flags.renewable = 0;
793 et.flags.pre_authent = tgt->flags.pre_authent;
794 et.flags.hw_authent = tgt->flags.hw_authent;
795 et.flags.anonymous = tgt->flags.anonymous;
796 et.flags.ok_as_delegate = server->entry.flags.ok_as_delegate;
799 /* XXX Check enc-authorization-data */
800 et.authorization_data = calloc(1, sizeof(*et.authorization_data));
801 if (et.authorization_data == NULL) {
805 ret = copy_AuthorizationData(auth_data, et.authorization_data);
809 /* Filter out type KRB5SignedPath */
810 ret = find_KRB5SignedPath(context, et.authorization_data, NULL);
812 if (et.authorization_data->len == 1) {
813 free_AuthorizationData(et.authorization_data);
814 free(et.authorization_data);
815 et.authorization_data = NULL;
817 AuthorizationData *ad = et.authorization_data;
818 free_AuthorizationDataElement(&ad->val[ad->len - 1]);
826 * No not need to filter out the any PAC from the
827 * auth_data since it's signed by the KDC.
829 ret = _kdc_tkt_add_if_relevant_ad(context, &et,
830 KRB5_AUTHDATA_WIN2K_PAC,
836 ret = krb5_copy_keyblock_contents(context, sessionkey, &et.key);
839 et.crealm = tgt->crealm;
840 et.cname = tgt_name->name;
843 /* MIT must have at least one last_req */
845 ek.last_req.val = calloc(1, sizeof(*ek.last_req.val));
846 if (ek.last_req.val == NULL) {
852 ek.authtime = et.authtime;
853 ek.starttime = et.starttime;
854 ek.endtime = et.endtime;
855 ek.renew_till = et.renew_till;
856 ek.srealm = rep.ticket.realm;
857 ek.sname = rep.ticket.sname;
859 _kdc_log_timestamp(context, config, "TGS-REQ", et.authtime, et.starttime,
860 et.endtime, et.renew_till);
862 /* Don't sign cross realm tickets, they can't be checked anyway */
864 char *r = get_krbtgt_realm(&ek.sname);
866 if (r == NULL || strcmp(r, ek.srealm) == 0) {
867 ret = _kdc_add_KRB5SignedPath(context,
879 if (enc_pa_data->len) {
880 rep.padata = calloc(1, sizeof(*rep.padata));
881 if (rep.padata == NULL) {
885 ret = copy_METHOD_DATA(enc_pa_data, rep.padata);
890 if (krb5_enctype_valid(context, et.key.keytype) != 0
891 && _kdc_is_weak_expection(server->entry.principal, et.key.keytype))
893 krb5_enctype_enable(context, et.key.keytype);
898 /* It is somewhat unclear where the etype in the following
899 encryption should come from. What we have is a session
900 key in the passed tgt, and a list of preferred etypes
901 *for the new ticket*. Should we pick the best possible
902 etype, given the keytype in the tgt, or should we look
903 at the etype list here as well? What if the tgt
904 session key is DES3 and we want a ticket with a (say)
905 CAST session key. Should the DES3 etype be added to the
906 etype list, even if we don't want a session key with
908 ret = _kdc_encode_reply(context, config,
909 &rep, &et, &ek, et.key.keytype,
911 serverkey, 0, &tgt->key, e_text, reply);
913 krb5_enctype_disable(context, et.key.keytype);
917 free_TransitedEncoding(&et.transited);
922 if(et.authorization_data) {
923 free_AuthorizationData(et.authorization_data);
924 free(et.authorization_data);
926 free_LastReq(&ek.last_req);
927 memset(et.key.keyvalue.data, 0, et.key.keyvalue.length);
928 free_EncryptionKey(&et.key);
932 static krb5_error_code
933 tgs_check_authenticator(krb5_context context,
934 krb5_kdc_configuration *config,
935 krb5_auth_context ac,
940 krb5_authenticator auth;
947 krb5_auth_con_getauthenticator(context, ac, &auth);
948 if(auth->cksum == NULL){
949 kdc_log(context, config, 0, "No authenticator in request");
950 ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
954 * according to RFC1510 it doesn't need to be keyed,
955 * but according to the latest draft it needs to.
959 !krb5_checksum_is_keyed(context, auth->cksum->cksumtype)
962 !krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) {
963 kdc_log(context, config, 0, "Bad checksum type in authenticator: %d",
964 auth->cksum->cksumtype);
965 ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
969 /* XXX should not re-encode this */
970 ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret);
972 kdc_log(context, config, 0, "Failed to encode KDC-REQ-BODY: %s",
973 krb5_get_err_text(context, ret));
976 if(buf_size != len) {
978 kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
979 *e_text = "KDC internal error";
980 ret = KRB5KRB_ERR_GENERIC;
983 ret = krb5_crypto_init(context, key, 0, &crypto);
986 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
987 krb5_get_err_text(context, ret));
990 ret = krb5_verify_checksum(context,
992 KRB5_KU_TGS_REQ_AUTH_CKSUM,
997 krb5_crypto_destroy(context, crypto);
999 kdc_log(context, config, 0,
1000 "Failed to verify authenticator checksum: %s",
1001 krb5_get_err_text(context, ret));
1004 free_Authenticator(auth);
1014 find_rpath(krb5_context context, Realm crealm, Realm srealm)
1016 const char *new_realm = krb5_config_get_string(context,
1027 need_referral(krb5_context context, krb5_kdc_configuration *config,
1028 const KDCOptions * const options, krb5_principal server,
1029 krb5_realm **realms)
1033 if(!options->canonicalize && server->name.name_type != KRB5_NT_SRV_INST)
1036 if (server->name.name_string.len == 1)
1037 name = server->name.name_string.val[0];
1038 if (server->name.name_string.len > 1)
1039 name = server->name.name_string.val[1];
1043 kdc_log(context, config, 0, "Searching referral for %s", name);
1045 return _krb5_get_host_realm_int(context, name, FALSE, realms) == 0;
1048 static krb5_error_code
1049 tgs_parse_request(krb5_context context,
1050 krb5_kdc_configuration *config,
1052 const PA_DATA *tgs_req,
1053 hdb_entry_ex **krbtgt,
1054 krb5_enctype *krbtgt_etype,
1055 krb5_ticket **ticket,
1056 const char **e_text,
1058 const struct sockaddr *from_addr,
1061 AuthorizationData **auth_data)
1064 krb5_error_code ret;
1065 krb5_principal princ;
1066 krb5_auth_context ac = NULL;
1067 krb5_flags ap_req_options;
1068 krb5_flags verify_ap_req_flags;
1076 memset(&ap_req, 0, sizeof(ap_req));
1077 ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req);
1079 kdc_log(context, config, 0, "Failed to decode AP-REQ: %s",
1080 krb5_get_err_text(context, ret));
1084 if(!get_krbtgt_realm(&ap_req.ticket.sname)){
1085 /* XXX check for ticket.sname == req.sname */
1086 kdc_log(context, config, 0, "PA-DATA is not a ticket-granting ticket");
1087 ret = KRB5KDC_ERR_POLICY; /* ? */
1091 _krb5_principalname2krb5_principal(context,
1093 ap_req.ticket.sname,
1094 ap_req.ticket.realm);
1096 ret = _kdc_db_fetch(context, config, princ, HDB_F_GET_KRBTGT, NULL, krbtgt);
1100 ret = krb5_unparse_name(context, princ, &p);
1102 p = "<unparse_name failed>";
1103 krb5_free_principal(context, princ);
1104 kdc_log(context, config, 0,
1105 "Ticket-granting ticket not found in database: %s: %s",
1106 p, krb5_get_err_text(context, ret));
1109 ret = KRB5KRB_AP_ERR_NOT_US;
1113 if(ap_req.ticket.enc_part.kvno &&
1114 *ap_req.ticket.enc_part.kvno != (*krbtgt)->entry.kvno){
1117 ret = krb5_unparse_name (context, princ, &p);
1118 krb5_free_principal(context, princ);
1120 p = "<unparse_name failed>";
1121 kdc_log(context, config, 0,
1122 "Ticket kvno = %d, DB kvno = %d (%s)",
1123 *ap_req.ticket.enc_part.kvno,
1124 (*krbtgt)->entry.kvno,
1128 ret = KRB5KRB_AP_ERR_BADKEYVER;
1132 *krbtgt_etype = ap_req.ticket.enc_part.etype;
1134 ret = hdb_enctype2key(context, &(*krbtgt)->entry,
1135 ap_req.ticket.enc_part.etype, &tkey);
1137 char *str = NULL, *p = NULL;
1139 krb5_enctype_to_string(context, ap_req.ticket.enc_part.etype, &str);
1140 krb5_unparse_name(context, princ, &p);
1141 kdc_log(context, config, 0,
1142 "No server key with enctype %s found for %s",
1143 str ? str : "<unknown enctype>",
1144 p ? p : "<unparse_name failed>");
1147 ret = KRB5KRB_AP_ERR_BADKEYVER;
1151 if (b->kdc_options.validate)
1152 verify_ap_req_flags = KRB5_VERIFY_AP_REQ_IGNORE_INVALID;
1154 verify_ap_req_flags = 0;
1156 ret = krb5_verify_ap_req2(context,
1161 verify_ap_req_flags,
1164 KRB5_KU_TGS_REQ_AUTH);
1166 krb5_free_principal(context, princ);
1168 kdc_log(context, config, 0, "Failed to verify AP-REQ: %s",
1169 krb5_get_err_text(context, ret));
1174 krb5_authenticator auth;
1176 ret = krb5_auth_con_getauthenticator(context, ac, &auth);
1178 *csec = malloc(sizeof(**csec));
1179 if (*csec == NULL) {
1180 krb5_free_authenticator(context, &auth);
1181 kdc_log(context, config, 0, "malloc failed");
1184 **csec = auth->ctime;
1185 *cusec = malloc(sizeof(**cusec));
1186 if (*cusec == NULL) {
1187 krb5_free_authenticator(context, &auth);
1188 kdc_log(context, config, 0, "malloc failed");
1191 **cusec = auth->cusec;
1192 krb5_free_authenticator(context, &auth);
1196 ret = tgs_check_authenticator(context, config,
1197 ac, b, e_text, &(*ticket)->ticket.key);
1199 krb5_auth_con_free(context, ac);
1203 if (b->enc_authorization_data) {
1204 unsigned usage = KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY;
1205 krb5_keyblock *subkey;
1208 ret = krb5_auth_con_getremotesubkey(context,
1212 krb5_auth_con_free(context, ac);
1213 kdc_log(context, config, 0, "Failed to get remote subkey: %s",
1214 krb5_get_err_text(context, ret));
1218 usage = KRB5_KU_TGS_REQ_AUTH_DAT_SESSION;
1219 ret = krb5_auth_con_getkey(context, ac, &subkey);
1221 krb5_auth_con_free(context, ac);
1222 kdc_log(context, config, 0, "Failed to get session key: %s",
1223 krb5_get_err_text(context, ret));
1228 krb5_auth_con_free(context, ac);
1229 kdc_log(context, config, 0,
1230 "Failed to get key for enc-authorization-data");
1231 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1234 ret = krb5_crypto_init(context, subkey, 0, &crypto);
1236 krb5_auth_con_free(context, ac);
1237 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
1238 krb5_get_err_text(context, ret));
1241 ret = krb5_decrypt_EncryptedData (context,
1244 b->enc_authorization_data,
1246 krb5_crypto_destroy(context, crypto);
1248 krb5_auth_con_free(context, ac);
1249 kdc_log(context, config, 0,
1250 "Failed to decrypt enc-authorization-data");
1251 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1254 krb5_free_keyblock(context, subkey);
1256 if (*auth_data == NULL) {
1257 krb5_auth_con_free(context, ac);
1258 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1261 ret = decode_AuthorizationData(ad.data, ad.length, *auth_data, NULL);
1263 krb5_auth_con_free(context, ac);
1266 kdc_log(context, config, 0, "Failed to decode authorization data");
1267 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1272 krb5_auth_con_free(context, ac);
1275 free_AP_REQ(&ap_req);
1280 static krb5_error_code
1281 build_server_referral(krb5_context context,
1282 krb5_kdc_configuration *config,
1283 krb5_crypto session,
1284 krb5_const_realm referred_realm,
1285 const PrincipalName *true_principal_name,
1286 const PrincipalName *requested_principal,
1289 PA_ServerReferralData ref;
1290 krb5_error_code ret;
1295 memset(&ref, 0, sizeof(ref));
1297 if (referred_realm) {
1298 ref.referred_realm = malloc(sizeof(ref.referred_realm));
1299 if (ref.referred_realm == NULL)
1301 *ref.referred_realm = strdup(referred_realm);
1302 if (*ref.referred_realm == NULL)
1305 if (true_principal_name) {
1306 ref.true_principal_name =
1307 malloc(sizeof(ref.true_principal_name));
1308 if (ref.true_principal_name == NULL)
1310 ret = copy_PrincipalName(true_principal_name, ref.true_principal_name);
1314 if (requested_principal) {
1315 ref.requested_principal_name =
1316 malloc(sizeof(ref.requested_principal_name));
1317 if (ref.requested_principal_name == NULL)
1319 ret = copy_PrincipalName(requested_principal,
1320 ref.requested_principal_name);
1325 ASN1_MALLOC_ENCODE(PA_ServerReferralData,
1326 data.data, data.length,
1328 free_PA_ServerReferralData(&ref);
1331 if (data.length != size)
1332 krb5_abortx(context, "internal asn.1 encoder error");
1334 ret = krb5_encrypt_EncryptedData(context, session,
1335 KRB5_KU_PA_SERVER_REFERRAL,
1336 data.data, data.length,
1342 ASN1_MALLOC_ENCODE(EncryptedData,
1343 outdata->data, outdata->length,
1345 free_EncryptedData(&ed);
1348 if (outdata->length != size)
1349 krb5_abortx(context, "internal asn.1 encoder error");
1353 free_PA_ServerReferralData(&ref);
1354 krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
1358 static krb5_error_code
1359 tgs_build_reply(krb5_context context,
1360 krb5_kdc_configuration *config,
1363 hdb_entry_ex *krbtgt,
1364 krb5_enctype krbtgt_etype,
1365 krb5_ticket *ticket,
1368 const char **e_text,
1369 AuthorizationData **auth_data,
1370 const struct sockaddr *from_addr,
1373 krb5_error_code ret;
1374 krb5_principal cp = NULL, sp = NULL;
1375 krb5_principal client_principal = NULL;
1376 char *spn = NULL, *cpn = NULL;
1377 hdb_entry_ex *server = NULL, *client = NULL;
1378 krb5_realm ref_realm = NULL;
1379 EncTicketPart *tgt = &ticket->ticket;
1380 KRB5SignedPathPrincipals *spp = NULL;
1381 const EncryptionKey *ekey;
1382 krb5_keyblock sessionkey;
1385 int cross_realm = 0;
1387 METHOD_DATA enc_pa_data;
1392 EncTicketPart adtkt;
1396 memset(&sessionkey, 0, sizeof(sessionkey));
1397 memset(&adtkt, 0, sizeof(adtkt));
1398 krb5_data_zero(&rspac);
1399 memset(&enc_pa_data, 0, sizeof(enc_pa_data));
1404 if(b->kdc_options.enc_tkt_in_skey){
1410 if(b->additional_tickets == NULL ||
1411 b->additional_tickets->len == 0){
1412 ret = KRB5KDC_ERR_BADOPTION; /* ? */
1413 kdc_log(context, config, 0,
1414 "No second ticket present in request");
1417 t = &b->additional_tickets->val[0];
1418 if(!get_krbtgt_realm(&t->sname)){
1419 kdc_log(context, config, 0,
1420 "Additional ticket is not a ticket-granting ticket");
1421 ret = KRB5KDC_ERR_POLICY;
1424 _krb5_principalname2krb5_principal(context, &p, t->sname, t->realm);
1425 ret = _kdc_db_fetch(context, config, p,
1426 HDB_F_GET_CLIENT|HDB_F_GET_SERVER,
1428 krb5_free_principal(context, p);
1430 if (ret == HDB_ERR_NOENTRY)
1431 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1434 ret = hdb_enctype2key(context, &uu->entry,
1435 t->enc_part.etype, &uukey);
1437 _kdc_free_ent(context, uu);
1438 ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
1441 ret = krb5_decrypt_ticket(context, t, &uukey->key, &adtkt, 0);
1442 _kdc_free_ent(context, uu);
1446 ret = verify_flags(context, config, &adtkt, spn);
1454 _krb5_principalname2krb5_principal(context, &sp, *s, r);
1455 ret = krb5_unparse_name(context, sp, &spn);
1458 _krb5_principalname2krb5_principal(context, &cp, tgt->cname, tgt->crealm);
1459 ret = krb5_unparse_name(context, cp, &cpn);
1462 unparse_flags (KDCOptions2int(b->kdc_options),
1463 asn1_KDCOptions_units(),
1464 opt_str, sizeof(opt_str));
1466 kdc_log(context, config, 0,
1467 "TGS-REQ %s from %s for %s [%s]",
1468 cpn, from, spn, opt_str);
1470 kdc_log(context, config, 0,
1471 "TGS-REQ %s from %s for %s", cpn, from, spn);
1478 ret = _kdc_db_fetch(context, config, sp, HDB_F_GET_SERVER | HDB_F_CANON,
1482 const char *new_rlm;
1486 if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) {
1488 new_rlm = find_rpath(context, tgt->crealm, req_rlm);
1490 kdc_log(context, config, 5, "krbtgt for realm %s "
1491 "not found, trying %s",
1493 krb5_free_principal(context, sp);
1495 krb5_make_principal(context, &sp, r,
1496 KRB5_TGS_NAME, new_rlm, NULL);
1497 ret = krb5_unparse_name(context, sp, &spn);
1503 ref_realm = strdup(new_rlm);
1507 } else if(need_referral(context, config, &b->kdc_options, sp, &realms)) {
1508 if (strcmp(realms[0], sp->realm) != 0) {
1509 kdc_log(context, config, 5,
1510 "Returning a referral to realm %s for "
1511 "server %s that was not found",
1513 krb5_free_principal(context, sp);
1515 krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
1517 ret = krb5_unparse_name(context, sp, &spn);
1523 ref_realm = strdup(realms[0]);
1525 krb5_free_host_realm(context, realms);
1528 krb5_free_host_realm(context, realms);
1530 kdc_log(context, config, 0,
1531 "Server not found in database: %s: %s", spn,
1532 krb5_get_err_text(context, ret));
1533 if (ret == HDB_ERR_NOENTRY)
1534 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1538 ret = _kdc_db_fetch(context, config, cp, HDB_F_GET_CLIENT | HDB_F_CANON,
1541 const char *krbtgt_realm;
1544 * If the client belongs to the same realm as our krbtgt, it
1545 * should exist in the local database.
1550 krb5_principal_get_comp_string(context,
1551 krbtgt->entry.principal, 1);
1553 if(strcmp(krb5_principal_get_realm(context, cp), krbtgt_realm) == 0) {
1554 if (ret == HDB_ERR_NOENTRY)
1555 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
1556 kdc_log(context, config, 1, "Client no longer in database: %s",
1561 kdc_log(context, config, 1, "Client not found in database: %s: %s",
1562 cpn, krb5_get_err_text(context, ret));
1568 * Select enctype, return key and kvno.
1574 if(b->kdc_options.enc_tkt_in_skey) {
1577 for(i = 0; i < b->etype.len; i++)
1578 if (b->etype.val[i] == adtkt.key.keytype)
1580 if(i == b->etype.len) {
1581 kdc_log(context, config, 0,
1582 "Addition ticket have not matching etypes", spp);
1583 krb5_clear_error_string(context);
1584 return KRB5KDC_ERR_ETYPE_NOSUPP;
1586 etype = b->etype.val[i];
1591 ret = _kdc_find_etype(context, server, b->etype.val, b->etype.len,
1594 kdc_log(context, config, 0,
1595 "Server (%s) has no support for etypes", spn);
1599 kvno = server->entry.kvno;
1602 ret = krb5_generate_random_keyblock(context, etype, &sessionkey);
1608 * Validate authoriation data
1612 * Check that service is in the same realm as the krbtgt. If it's
1613 * not the same, it's someone that is using a uni-directional trust
1617 if (strcmp(krb5_principal_get_realm(context, sp),
1618 krb5_principal_get_comp_string(context,
1619 krbtgt->entry.principal,
1622 ret = krb5_unparse_name(context, krbtgt->entry.principal, &tpn);
1623 kdc_log(context, config, 0,
1624 "Request with wrong krbtgt: %s",
1625 (ret == 0) ? tpn : "<unknown>");
1628 ret = KRB5KRB_AP_ERR_NOT_US;
1632 /* check PAC if not cross realm and if there is one */
1636 ret = hdb_enctype2key(context, &krbtgt->entry,
1637 krbtgt_etype, &tkey);
1639 kdc_log(context, config, 0,
1640 "Failed to find key for krbtgt PAC check");
1644 ret = check_PAC(context, config, cp,
1645 client, server, ekey, &tkey->key,
1646 tgt, &rspac, &signedpath);
1648 kdc_log(context, config, 0,
1649 "Verify PAC failed for %s (%s) from %s with %s",
1650 spn, cpn, from, krb5_get_err_text(context, ret));
1655 /* also check the krbtgt for signature */
1656 ret = check_KRB5SignedPath(context,
1663 kdc_log(context, config, 0,
1664 "KRB5SignedPath check failed for %s (%s) from %s with %s",
1665 spn, cpn, from, krb5_get_err_text(context, ret));
1673 client_principal = cp;
1676 const PA_DATA *sdata;
1679 sdata = _kdc_find_padata(req, &i, KRB5_PADATA_S4U2SELF);
1684 char *selfcpn = NULL;
1687 ret = decode_PA_S4U2Self(sdata->padata_value.data,
1688 sdata->padata_value.length,
1691 kdc_log(context, config, 0, "Failed to decode PA-S4U2Self");
1695 ret = _krb5_s4u2self_to_checksumdata(context, &self, &datack);
1699 ret = krb5_crypto_init(context, &tgt->key, 0, &crypto);
1701 free_PA_S4U2Self(&self);
1702 krb5_data_free(&datack);
1703 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
1704 krb5_get_err_text(context, ret));
1708 ret = krb5_verify_checksum(context,
1710 KRB5_KU_OTHER_CKSUM,
1714 krb5_data_free(&datack);
1715 krb5_crypto_destroy(context, crypto);
1717 free_PA_S4U2Self(&self);
1718 kdc_log(context, config, 0,
1719 "krb5_verify_checksum failed for S4U2Self: %s",
1720 krb5_get_err_text(context, ret));
1724 ret = _krb5_principalname2krb5_principal(context,
1728 free_PA_S4U2Self(&self);
1732 ret = krb5_unparse_name(context, client_principal, &selfcpn);
1737 * Check that service doing the impersonating is
1738 * requesting a ticket to it-self.
1740 if (krb5_principal_compare(context, cp, sp) != TRUE) {
1741 kdc_log(context, config, 0, "S4U2Self: %s is not allowed "
1742 "to impersonate some other user "
1743 "(tried for user %s to service %s)",
1746 ret = KRB5KDC_ERR_BADOPTION; /* ? */
1751 * If the service isn't trusted for authentication to
1752 * delegation, remove the forward flag.
1755 if (client->entry.flags.trusted_for_delegation) {
1756 str = "[forwardable]";
1758 b->kdc_options.forwardable = 0;
1761 kdc_log(context, config, 0, "s4u2self %s impersonating %s to "
1762 "service %s %s", cpn, selfcpn, spn, str);
1768 * Constrained delegation
1772 && b->additional_tickets != NULL
1773 && b->additional_tickets->len != 0
1774 && b->kdc_options.enc_tkt_in_skey == 0)
1776 int ad_signedpath = 0;
1782 * Require that the KDC have issued the service's krbtgt (not
1783 * self-issued ticket with kimpersonate(1).
1786 ret = KRB5KDC_ERR_BADOPTION;
1787 kdc_log(context, config, 0,
1788 "Constrained delegation done on service ticket %s/%s",
1793 t = &b->additional_tickets->val[0];
1795 ret = hdb_enctype2key(context, &client->entry,
1796 t->enc_part.etype, &clientkey);
1798 ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
1802 ret = krb5_decrypt_ticket(context, t, &clientkey->key, &adtkt, 0);
1804 kdc_log(context, config, 0,
1805 "failed to decrypt ticket for "
1806 "constrained delegation from %s to %s ", spn, cpn);
1810 /* check that ticket is valid */
1811 if (adtkt.flags.forwardable == 0) {
1812 kdc_log(context, config, 0,
1813 "Missing forwardable flag on ticket for "
1814 "constrained delegation from %s to %s ", spn, cpn);
1815 ret = KRB5KDC_ERR_BADOPTION;
1819 ret = check_constrained_delegation(context, config, client, sp);
1821 kdc_log(context, config, 0,
1822 "constrained delegation from %s to %s not allowed",
1827 ret = _krb5_principalname2krb5_principal(context,
1834 ret = krb5_unparse_name(context, client_principal, &str);
1838 ret = verify_flags(context, config, &adtkt, str);
1845 * Check that the KDC issued the user's ticket.
1847 ret = check_KRB5SignedPath(context,
1853 if (ret == 0 && !ad_signedpath)
1854 ret = KRB5KDC_ERR_BADOPTION;
1856 kdc_log(context, config, 0,
1857 "KRB5SignedPath check from service %s failed "
1858 "for delegation to %s for client %s "
1859 "from %s failed with %s",
1860 spn, str, cpn, from, krb5_get_err_text(context, ret));
1865 kdc_log(context, config, 0, "constrained delegation for %s "
1866 "from %s to %s", str, cpn, spn);
1874 ret = _kdc_check_flags(context, config,
1881 if((b->kdc_options.validate || b->kdc_options.renew) &&
1882 !krb5_principal_compare(context,
1883 krbtgt->entry.principal,
1884 server->entry.principal)){
1885 kdc_log(context, config, 0, "Inconsistent request.");
1886 ret = KRB5KDC_ERR_SERVER_NOMATCH;
1890 /* check for valid set of addresses */
1891 if(!_kdc_check_addresses(context, config, tgt->caddr, from_addr)) {
1892 ret = KRB5KRB_AP_ERR_BADADDR;
1893 kdc_log(context, config, 0, "Request from wrong address");
1898 * If this is an referral, add server referral data to the
1905 kdc_log(context, config, 0,
1906 "Adding server referral to %s", ref_realm);
1908 ret = krb5_crypto_init(context, &sessionkey, 0, &crypto);
1912 ret = build_server_referral(context, config, crypto, ref_realm,
1913 NULL, s, &pa.padata_value);
1914 krb5_crypto_destroy(context, crypto);
1916 kdc_log(context, config, 0,
1917 "Failed building server referral");
1920 pa.padata_type = KRB5_PADATA_SERVER_REFERRAL;
1922 ret = add_METHOD_DATA(&enc_pa_data, &pa);
1923 krb5_data_free(&pa.padata_value);
1925 kdc_log(context, config, 0,
1926 "Add server referral METHOD-DATA failed");
1935 ret = tgs_make_reply(context,
1961 krb5_data_free(&rspac);
1962 krb5_free_keyblock_contents(context, &sessionkey);
1964 _kdc_free_ent(context, server);
1966 _kdc_free_ent(context, client);
1968 if (client_principal && client_principal != cp)
1969 krb5_free_principal(context, client_principal);
1971 krb5_free_principal(context, cp);
1973 krb5_free_principal(context, sp);
1976 free_METHOD_DATA(&enc_pa_data);
1978 free_EncTicketPart(&adtkt);
1988 _kdc_tgs_rep(krb5_context context,
1989 krb5_kdc_configuration *config,
1993 struct sockaddr *from_addr,
1996 AuthorizationData *auth_data = NULL;
1997 krb5_error_code ret;
1999 const PA_DATA *tgs_req;
2001 hdb_entry_ex *krbtgt = NULL;
2002 krb5_ticket *ticket = NULL;
2003 const char *e_text = NULL;
2004 krb5_enctype krbtgt_etype = ETYPE_NULL;
2006 time_t *csec = NULL;
2009 if(req->padata == NULL){
2010 ret = KRB5KDC_ERR_PREAUTH_REQUIRED; /* XXX ??? */
2011 kdc_log(context, config, 0,
2012 "TGS-REQ from %s without PA-DATA", from);
2016 tgs_req = _kdc_find_padata(req, &i, KRB5_PADATA_TGS_REQ);
2018 if(tgs_req == NULL){
2019 ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
2021 kdc_log(context, config, 0,
2022 "TGS-REQ from %s without PA-TGS-REQ", from);
2025 ret = tgs_parse_request(context, config,
2026 &req->req_body, tgs_req,
2035 kdc_log(context, config, 0,
2036 "Failed parsing TGS-REQ from %s", from);
2040 ret = tgs_build_reply(context,
2054 kdc_log(context, config, 0,
2055 "Failed building TGS-REP to %s", from);
2060 if (datagram_reply && data->length > config->max_datagram_reply_length) {
2061 krb5_data_free(data);
2062 ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
2063 e_text = "Reply packet too large";
2067 if(ret && data->data == NULL){
2068 krb5_mk_error(context,
2081 krb5_free_ticket(context, ticket);
2083 _kdc_free_ent(context, krbtgt);
2086 free_AuthorizationData(auth_data);