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
37 * return the realm of a krbtgt-ticket or NULL
41 get_krbtgt_realm(const PrincipalName *p)
43 if(p->name_string.len == 2
44 && strcmp(p->name_string.val[0], KRB5_TGS_NAME) == 0)
45 return p->name_string.val[1];
51 * The KDC might add a signed path to the ticket authorization data
52 * field. This is to avoid server impersonating clients and the
53 * request constrained delegation.
55 * This is done by storing a KRB5_AUTHDATA_IF_RELEVANT with a single
56 * entry of type KRB5SignedPath.
59 static krb5_error_code
60 find_KRB5SignedPath(krb5_context context,
61 const AuthorizationData *ad,
64 AuthorizationData child;
68 if (ad == NULL || ad->len == 0)
69 return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
73 if (ad->val[pos].ad_type != KRB5_AUTHDATA_IF_RELEVANT)
74 return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
76 ret = decode_AuthorizationData(ad->val[pos].ad_data.data,
77 ad->val[pos].ad_data.length,
81 krb5_set_error_message(context, ret, "Failed to decode "
82 "IF_RELEVANT with %d", ret);
87 free_AuthorizationData(&child);
88 return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
91 if (child.val[0].ad_type != KRB5_AUTHDATA_SIGNTICKET) {
92 free_AuthorizationData(&child);
93 return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
97 ret = der_copy_octet_string(&child.val[0].ad_data, data);
98 free_AuthorizationData(&child);
103 _kdc_add_KRB5SignedPath(krb5_context context,
104 krb5_kdc_configuration *config,
105 hdb_entry_ex *krbtgt,
106 krb5_enctype enctype,
107 krb5_principal client,
108 krb5_const_principal server,
109 krb5_principals principals,
115 krb5_crypto crypto = NULL;
118 if (server && principals) {
119 ret = add_Principals(principals, server);
125 KRB5SignedPathData spd;
128 spd.authtime = tkt->authtime;
129 spd.delegated = principals;
130 spd.method_data = NULL;
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;
157 sp.method_data = NULL;
159 ret = krb5_create_checksum(context, crypto, KRB5_KU_KRB5SIGNEDPATH, 0,
160 data.data, data.length, &sp.cksum);
161 krb5_crypto_destroy(context, crypto);
166 ASN1_MALLOC_ENCODE(KRB5SignedPath, data.data, data.length, &sp, &size, ret);
167 free_Checksum(&sp.cksum);
170 if (data.length != size)
171 krb5_abortx(context, "internal asn.1 encoder error");
175 * Add IF-RELEVANT(KRB5SignedPath) to the last slot in
176 * authorization data field.
179 ret = _kdc_tkt_add_if_relevant_ad(context, tkt,
180 KRB5_AUTHDATA_SIGNTICKET, &data);
181 krb5_data_free(&data);
186 static krb5_error_code
187 check_KRB5SignedPath(krb5_context context,
188 krb5_kdc_configuration *config,
189 hdb_entry_ex *krbtgt,
192 krb5_principals *delegated,
197 krb5_crypto crypto = NULL;
202 ret = find_KRB5SignedPath(context, tkt->authorization_data, &data);
204 KRB5SignedPathData spd;
208 ret = decode_KRB5SignedPath(data.data, data.length, &sp, NULL);
209 krb5_data_free(&data);
214 spd.authtime = tkt->authtime;
215 spd.delegated = sp.delegated;
216 spd.method_data = sp.method_data;
218 ASN1_MALLOC_ENCODE(KRB5SignedPathData, data.data, data.length,
221 free_KRB5SignedPath(&sp);
224 if (data.length != size)
225 krb5_abortx(context, "internal asn.1 encoder error");
229 ret = hdb_enctype2key(context, &krbtgt->entry, sp.etype, &key);
231 ret = krb5_crypto_init(context, &key->key, 0, &crypto);
234 free_KRB5SignedPath(&sp);
238 ret = krb5_verify_checksum(context, crypto, KRB5_KU_KRB5SIGNEDPATH,
239 data.data, data.length,
241 krb5_crypto_destroy(context, crypto);
244 free_KRB5SignedPath(&sp);
245 kdc_log(context, config, 5,
246 "KRB5SignedPath not signed correctly, not marking as signed");
250 if (delegated && sp.delegated) {
252 *delegated = malloc(sizeof(*sp.delegated));
253 if (*delegated == NULL) {
254 free_KRB5SignedPath(&sp);
258 ret = copy_Principals(*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,
496 hdb_entry_ex *client,
497 krb5_const_principal server)
499 const HDB_Ext_Constrained_delegation_acl *acl;
503 /* if client delegates to itself, that ok */
504 if (krb5_principal_compare(context, client->entry.principal, server) == TRUE)
507 if (clientdb->hdb_check_constrained_delegation) {
508 ret = clientdb->hdb_check_constrained_delegation(context, clientdb, client, server);
512 ret = hdb_entry_get_ConstrainedDelegACL(&client->entry, &acl);
514 krb5_clear_error_message(context);
519 for (i = 0; i < acl->len; i++) {
520 if (krb5_principal_compare(context, server, &acl->val[i]) == TRUE)
524 ret = KRB5KDC_ERR_BADOPTION;
526 kdc_log(context, config, 0,
527 "Bad request for constrained delegation");
535 static krb5_error_code
536 verify_flags (krb5_context context,
537 krb5_kdc_configuration *config,
538 const EncTicketPart *et,
541 if(et->endtime < kdc_time){
542 kdc_log(context, config, 0, "Ticket expired (%s)", pstr);
543 return KRB5KRB_AP_ERR_TKT_EXPIRED;
545 if(et->flags.invalid){
546 kdc_log(context, config, 0, "Ticket not valid (%s)", pstr);
547 return KRB5KRB_AP_ERR_TKT_NYV;
556 static krb5_error_code
557 fix_transited_encoding(krb5_context context,
558 krb5_kdc_configuration *config,
559 krb5_boolean check_policy,
560 const TransitedEncoding *tr,
562 const char *client_realm,
563 const char *server_realm,
564 const char *tgt_realm)
566 krb5_error_code ret = 0;
567 char **realms, **tmp;
568 unsigned int num_realms;
571 switch (tr->tr_type) {
572 case DOMAIN_X500_COMPRESS:
576 * Allow empty content of type 0 because that is was Microsoft
577 * generates in their TGT.
579 if (tr->contents.length == 0)
581 kdc_log(context, config, 0,
582 "Transited type 0 with non empty content");
583 return KRB5KDC_ERR_TRTYPE_NOSUPP;
585 kdc_log(context, config, 0,
586 "Unknown transited type: %u", tr->tr_type);
587 return KRB5KDC_ERR_TRTYPE_NOSUPP;
590 ret = krb5_domain_x500_decode(context,
597 krb5_warn(context, ret,
598 "Decoding transited encoding");
601 if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) {
602 /* not us, so add the previous realm to transited set */
603 if (num_realms + 1 > UINT_MAX/sizeof(*realms)) {
607 tmp = realloc(realms, (num_realms + 1) * sizeof(*realms));
613 realms[num_realms] = strdup(tgt_realm);
614 if(realms[num_realms] == NULL){
620 if(num_realms == 0) {
621 if(strcmp(client_realm, server_realm))
622 kdc_log(context, config, 0,
623 "cross-realm %s -> %s", client_realm, server_realm);
627 for(i = 0; i < num_realms; i++)
628 l += strlen(realms[i]) + 2;
632 for(i = 0; i < num_realms; i++) {
634 strlcat(rs, ", ", l);
635 strlcat(rs, realms[i], l);
637 kdc_log(context, config, 0,
638 "cross-realm %s -> %s via [%s]",
639 client_realm, server_realm, rs);
644 ret = krb5_check_transited(context, client_realm,
646 realms, num_realms, NULL);
648 krb5_warn(context, ret, "cross-realm %s -> %s",
649 client_realm, server_realm);
652 et->flags.transited_policy_checked = 1;
654 et->transited.tr_type = DOMAIN_X500_COMPRESS;
655 ret = krb5_domain_x500_encode(realms, num_realms, &et->transited.contents);
657 krb5_warn(context, ret, "Encoding transited encoding");
659 for(i = 0; i < num_realms; i++)
666 static krb5_error_code
667 tgs_make_reply(krb5_context context,
668 krb5_kdc_configuration *config,
670 krb5_const_principal tgt_name,
671 const EncTicketPart *tgt,
672 const krb5_keyblock *replykey,
674 const EncryptionKey *serverkey,
675 const krb5_keyblock *sessionkey,
677 AuthorizationData *auth_data,
678 hdb_entry_ex *server,
679 krb5_principal server_principal,
680 const char *server_name,
681 hdb_entry_ex *client,
682 krb5_principal client_principal,
683 hdb_entry_ex *krbtgt,
684 krb5_enctype krbtgt_etype,
686 const krb5_data *rspac,
687 const METHOD_DATA *enc_pa_data,
694 KDCOptions f = b->kdc_options;
698 memset(&rep, 0, sizeof(rep));
699 memset(&et, 0, sizeof(et));
700 memset(&ek, 0, sizeof(ek));
703 rep.msg_type = krb_tgs_rep;
705 et.authtime = tgt->authtime;
706 _kdc_fix_time(&b->till);
707 et.endtime = min(tgt->endtime, *b->till);
709 *et.starttime = kdc_time;
711 ret = check_tgs_flags(context, config, b, tgt, &et);
715 /* We should check the transited encoding if:
716 1) the request doesn't ask not to be checked
717 2) globally enforcing a check
718 3) principal requires checking
719 4) we allow non-check per-principal, but principal isn't marked as allowing this
720 5) we don't globally allow this
723 #define GLOBAL_FORCE_TRANSITED_CHECK \
724 (config->trpolicy == TRPOLICY_ALWAYS_CHECK)
725 #define GLOBAL_ALLOW_PER_PRINCIPAL \
726 (config->trpolicy == TRPOLICY_ALLOW_PER_PRINCIPAL)
727 #define GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK \
728 (config->trpolicy == TRPOLICY_ALWAYS_HONOUR_REQUEST)
730 /* these will consult the database in future release */
731 #define PRINCIPAL_FORCE_TRANSITED_CHECK(P) 0
732 #define PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(P) 0
734 ret = fix_transited_encoding(context, config,
735 !f.disable_transited_check ||
736 GLOBAL_FORCE_TRANSITED_CHECK ||
737 PRINCIPAL_FORCE_TRANSITED_CHECK(server) ||
738 !((GLOBAL_ALLOW_PER_PRINCIPAL &&
739 PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server)) ||
740 GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK),
741 &tgt->transited, &et,
742 krb5_principal_get_realm(context, client_principal),
743 krb5_principal_get_realm(context, server->entry.principal),
744 krb5_principal_get_realm(context, krbtgt->entry.principal));
748 copy_Realm(&server_principal->realm, &rep.ticket.realm);
749 _krb5_principal2principalname(&rep.ticket.sname, server_principal);
750 copy_Realm(&tgt_name->realm, &rep.crealm);
752 if (f.request_anonymous)
753 _kdc_make_anonymous_principalname (&rep.cname);
756 copy_PrincipalName(&tgt_name->name, &rep.cname);
757 rep.ticket.tkt_vno = 5;
761 et.caddr = tgt->caddr;
765 life = et.endtime - *et.starttime;
766 if(client && client->entry.max_life)
767 life = min(life, *client->entry.max_life);
768 if(server->entry.max_life)
769 life = min(life, *server->entry.max_life);
770 et.endtime = *et.starttime + life;
772 if(f.renewable_ok && tgt->flags.renewable &&
773 et.renew_till == NULL && et.endtime < *b->till){
774 et.flags.renewable = 1;
775 ALLOC(et.renew_till);
776 *et.renew_till = *b->till;
780 renew = *et.renew_till - et.authtime;
781 if(client && client->entry.max_renew)
782 renew = min(renew, *client->entry.max_renew);
783 if(server->entry.max_renew)
784 renew = min(renew, *server->entry.max_renew);
785 *et.renew_till = et.authtime + renew;
789 *et.renew_till = min(*et.renew_till, *tgt->renew_till);
790 *et.starttime = min(*et.starttime, *et.renew_till);
791 et.endtime = min(et.endtime, *et.renew_till);
794 *et.starttime = min(*et.starttime, et.endtime);
796 if(*et.starttime == et.endtime){
797 ret = KRB5KDC_ERR_NEVER_VALID;
800 if(et.renew_till && et.endtime == *et.renew_till){
802 et.renew_till = NULL;
803 et.flags.renewable = 0;
806 et.flags.pre_authent = tgt->flags.pre_authent;
807 et.flags.hw_authent = tgt->flags.hw_authent;
808 et.flags.anonymous = tgt->flags.anonymous;
809 et.flags.ok_as_delegate = server->entry.flags.ok_as_delegate;
813 * No not need to filter out the any PAC from the
814 * auth_data since it's signed by the KDC.
816 ret = _kdc_tkt_add_if_relevant_ad(context, &et,
817 KRB5_AUTHDATA_WIN2K_PAC, rspac);
825 /* XXX check authdata */
827 if (et.authorization_data == NULL) {
828 et.authorization_data = calloc(1, sizeof(*et.authorization_data));
829 if (et.authorization_data == NULL) {
831 krb5_set_error_message(context, ret, "malloc: out of memory");
835 for(i = 0; i < auth_data->len ; i++) {
836 ret = add_AuthorizationData(et.authorization_data, &auth_data->val[i]);
838 krb5_set_error_message(context, ret, "malloc: out of memory");
843 /* Filter out type KRB5SignedPath */
844 ret = find_KRB5SignedPath(context, et.authorization_data, NULL);
846 if (et.authorization_data->len == 1) {
847 free_AuthorizationData(et.authorization_data);
848 free(et.authorization_data);
849 et.authorization_data = NULL;
851 AuthorizationData *ad = et.authorization_data;
852 free_AuthorizationDataElement(&ad->val[ad->len - 1]);
858 ret = krb5_copy_keyblock_contents(context, sessionkey, &et.key);
861 et.crealm = tgt->crealm;
862 et.cname = tgt_name->name;
865 /* MIT must have at least one last_req */
867 ek.last_req.val = calloc(1, sizeof(*ek.last_req.val));
868 if (ek.last_req.val == NULL) {
874 ek.authtime = et.authtime;
875 ek.starttime = et.starttime;
876 ek.endtime = et.endtime;
877 ek.renew_till = et.renew_till;
878 ek.srealm = rep.ticket.realm;
879 ek.sname = rep.ticket.sname;
881 _kdc_log_timestamp(context, config, "TGS-REQ", et.authtime, et.starttime,
882 et.endtime, et.renew_till);
884 /* Don't sign cross realm tickets, they can't be checked anyway */
886 char *r = get_krbtgt_realm(&ek.sname);
888 if (r == NULL || strcmp(r, ek.srealm) == 0) {
889 ret = _kdc_add_KRB5SignedPath(context,
902 if (enc_pa_data->len) {
903 rep.padata = calloc(1, sizeof(*rep.padata));
904 if (rep.padata == NULL) {
908 ret = copy_METHOD_DATA(enc_pa_data, rep.padata);
913 if (krb5_enctype_valid(context, et.key.keytype) != 0
914 && _kdc_is_weak_exception(server->entry.principal, et.key.keytype))
916 krb5_enctype_enable(context, et.key.keytype);
921 /* It is somewhat unclear where the etype in the following
922 encryption should come from. What we have is a session
923 key in the passed tgt, and a list of preferred etypes
924 *for the new ticket*. Should we pick the best possible
925 etype, given the keytype in the tgt, or should we look
926 at the etype list here as well? What if the tgt
927 session key is DES3 and we want a ticket with a (say)
928 CAST session key. Should the DES3 etype be added to the
929 etype list, even if we don't want a session key with
931 ret = _kdc_encode_reply(context, config,
932 &rep, &et, &ek, et.key.keytype,
934 serverkey, 0, replykey, rk_is_subkey,
937 krb5_enctype_disable(context, et.key.keytype);
941 free_TransitedEncoding(&et.transited);
946 if(et.authorization_data) {
947 free_AuthorizationData(et.authorization_data);
948 free(et.authorization_data);
950 free_LastReq(&ek.last_req);
951 memset(et.key.keyvalue.data, 0, et.key.keyvalue.length);
952 free_EncryptionKey(&et.key);
956 static krb5_error_code
957 tgs_check_authenticator(krb5_context context,
958 krb5_kdc_configuration *config,
959 krb5_auth_context ac,
964 krb5_authenticator auth;
971 krb5_auth_con_getauthenticator(context, ac, &auth);
972 if(auth->cksum == NULL){
973 kdc_log(context, config, 0, "No authenticator in request");
974 ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
978 * according to RFC1510 it doesn't need to be keyed,
979 * but according to the latest draft it needs to.
983 !krb5_checksum_is_keyed(context, auth->cksum->cksumtype)
986 !krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) {
987 kdc_log(context, config, 0, "Bad checksum type in authenticator: %d",
988 auth->cksum->cksumtype);
989 ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
993 /* XXX should not re-encode this */
994 ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret);
996 const char *msg = krb5_get_error_message(context, ret);
997 kdc_log(context, config, 0, "Failed to encode KDC-REQ-BODY: %s", msg);
998 krb5_free_error_message(context, msg);
1001 if(buf_size != len) {
1003 kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
1004 *e_text = "KDC internal error";
1005 ret = KRB5KRB_ERR_GENERIC;
1008 ret = krb5_crypto_init(context, key, 0, &crypto);
1010 const char *msg = krb5_get_error_message(context, ret);
1012 kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
1013 krb5_free_error_message(context, msg);
1016 ret = krb5_verify_checksum(context,
1018 KRB5_KU_TGS_REQ_AUTH_CKSUM,
1023 krb5_crypto_destroy(context, crypto);
1025 const char *msg = krb5_get_error_message(context, ret);
1026 kdc_log(context, config, 0,
1027 "Failed to verify authenticator checksum: %s", msg);
1028 krb5_free_error_message(context, msg);
1031 free_Authenticator(auth);
1041 find_rpath(krb5_context context, Realm crealm, Realm srealm)
1043 const char *new_realm = krb5_config_get_string(context,
1054 need_referral(krb5_context context, krb5_kdc_configuration *config,
1055 const KDCOptions * const options, krb5_principal server,
1056 krb5_realm **realms)
1060 if(!options->canonicalize && server->name.name_type != KRB5_NT_SRV_INST)
1063 if (server->name.name_string.len == 1)
1064 name = server->name.name_string.val[0];
1065 else if (server->name.name_string.len > 1)
1066 name = server->name.name_string.val[1];
1070 kdc_log(context, config, 0, "Searching referral for %s", name);
1072 return _krb5_get_host_realm_int(context, name, FALSE, realms) == 0;
1075 static krb5_error_code
1076 tgs_parse_request(krb5_context context,
1077 krb5_kdc_configuration *config,
1079 const PA_DATA *tgs_req,
1080 hdb_entry_ex **krbtgt,
1081 krb5_enctype *krbtgt_etype,
1082 krb5_ticket **ticket,
1083 const char **e_text,
1085 const struct sockaddr *from_addr,
1088 AuthorizationData **auth_data,
1089 krb5_keyblock **replykey,
1093 krb5_error_code ret;
1094 krb5_principal princ;
1095 krb5_auth_context ac = NULL;
1096 krb5_flags ap_req_options;
1097 krb5_flags verify_ap_req_flags;
1100 krb5_keyblock *subkey = NULL;
1108 memset(&ap_req, 0, sizeof(ap_req));
1109 ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req);
1111 const char *msg = krb5_get_error_message(context, ret);
1112 kdc_log(context, config, 0, "Failed to decode AP-REQ: %s", msg);
1113 krb5_free_error_message(context, msg);
1117 if(!get_krbtgt_realm(&ap_req.ticket.sname)){
1118 /* XXX check for ticket.sname == req.sname */
1119 kdc_log(context, config, 0, "PA-DATA is not a ticket-granting ticket");
1120 ret = KRB5KDC_ERR_POLICY; /* ? */
1124 _krb5_principalname2krb5_principal(context,
1126 ap_req.ticket.sname,
1127 ap_req.ticket.realm);
1129 ret = _kdc_db_fetch(context, config, princ, HDB_F_GET_KRBTGT, NULL, krbtgt);
1132 const char *msg = krb5_get_error_message(context, ret);
1134 ret = krb5_unparse_name(context, princ, &p);
1136 p = "<unparse_name failed>";
1137 krb5_free_principal(context, princ);
1138 kdc_log(context, config, 0,
1139 "Ticket-granting ticket not found in database: %s", msg);
1140 krb5_free_error_message(context, msg);
1143 ret = KRB5KRB_AP_ERR_NOT_US;
1147 if(ap_req.ticket.enc_part.kvno &&
1148 *ap_req.ticket.enc_part.kvno != (*krbtgt)->entry.kvno){
1151 ret = krb5_unparse_name (context, princ, &p);
1152 krb5_free_principal(context, princ);
1154 p = "<unparse_name failed>";
1155 kdc_log(context, config, 0,
1156 "Ticket kvno = %d, DB kvno = %d (%s)",
1157 *ap_req.ticket.enc_part.kvno,
1158 (*krbtgt)->entry.kvno,
1162 ret = KRB5KRB_AP_ERR_BADKEYVER;
1166 *krbtgt_etype = ap_req.ticket.enc_part.etype;
1168 ret = hdb_enctype2key(context, &(*krbtgt)->entry,
1169 ap_req.ticket.enc_part.etype, &tkey);
1171 char *str = NULL, *p = NULL;
1173 krb5_enctype_to_string(context, ap_req.ticket.enc_part.etype, &str);
1174 krb5_unparse_name(context, princ, &p);
1175 kdc_log(context, config, 0,
1176 "No server key with enctype %s found for %s",
1177 str ? str : "<unknown enctype>",
1178 p ? p : "<unparse_name failed>");
1181 ret = KRB5KRB_AP_ERR_BADKEYVER;
1185 if (b->kdc_options.validate)
1186 verify_ap_req_flags = KRB5_VERIFY_AP_REQ_IGNORE_INVALID;
1188 verify_ap_req_flags = 0;
1190 ret = krb5_verify_ap_req2(context,
1195 verify_ap_req_flags,
1198 KRB5_KU_TGS_REQ_AUTH);
1200 krb5_free_principal(context, princ);
1202 const char *msg = krb5_get_error_message(context, ret);
1203 kdc_log(context, config, 0, "Failed to verify AP-REQ: %s", msg);
1204 krb5_free_error_message(context, msg);
1209 krb5_authenticator auth;
1211 ret = krb5_auth_con_getauthenticator(context, ac, &auth);
1213 *csec = malloc(sizeof(**csec));
1214 if (*csec == NULL) {
1215 krb5_free_authenticator(context, &auth);
1216 kdc_log(context, config, 0, "malloc failed");
1219 **csec = auth->ctime;
1220 *cusec = malloc(sizeof(**cusec));
1221 if (*cusec == NULL) {
1222 krb5_free_authenticator(context, &auth);
1223 kdc_log(context, config, 0, "malloc failed");
1226 **cusec = auth->cusec;
1227 krb5_free_authenticator(context, &auth);
1231 ret = tgs_check_authenticator(context, config,
1232 ac, b, e_text, &(*ticket)->ticket.key);
1234 krb5_auth_con_free(context, ac);
1238 usage = KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY;
1241 ret = krb5_auth_con_getremotesubkey(context, ac, &subkey);
1243 const char *msg = krb5_get_error_message(context, ret);
1244 krb5_auth_con_free(context, ac);
1245 kdc_log(context, config, 0, "Failed to get remote subkey: %s", msg);
1246 krb5_free_error_message(context, msg);
1250 usage = KRB5_KU_TGS_REQ_AUTH_DAT_SESSION;
1253 ret = krb5_auth_con_getkey(context, ac, &subkey);
1255 const char *msg = krb5_get_error_message(context, ret);
1256 krb5_auth_con_free(context, ac);
1257 kdc_log(context, config, 0, "Failed to get session key: %s", msg);
1258 krb5_free_error_message(context, msg);
1263 krb5_auth_con_free(context, ac);
1264 kdc_log(context, config, 0,
1265 "Failed to get key for enc-authorization-data");
1266 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1272 if (b->enc_authorization_data) {
1275 ret = krb5_crypto_init(context, subkey, 0, &crypto);
1277 const char *msg = krb5_get_error_message(context, ret);
1278 krb5_auth_con_free(context, ac);
1279 kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
1280 krb5_free_error_message(context, msg);
1283 ret = krb5_decrypt_EncryptedData (context,
1286 b->enc_authorization_data,
1288 krb5_crypto_destroy(context, crypto);
1290 krb5_auth_con_free(context, ac);
1291 kdc_log(context, config, 0,
1292 "Failed to decrypt enc-authorization-data");
1293 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1297 if (*auth_data == NULL) {
1298 krb5_auth_con_free(context, ac);
1299 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1302 ret = decode_AuthorizationData(ad.data, ad.length, *auth_data, NULL);
1304 krb5_auth_con_free(context, ac);
1307 kdc_log(context, config, 0, "Failed to decode authorization data");
1308 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1313 krb5_auth_con_free(context, ac);
1316 free_AP_REQ(&ap_req);
1321 static krb5_error_code
1322 build_server_referral(krb5_context context,
1323 krb5_kdc_configuration *config,
1324 krb5_crypto session,
1325 krb5_const_realm referred_realm,
1326 const PrincipalName *true_principal_name,
1327 const PrincipalName *requested_principal,
1330 PA_ServerReferralData ref;
1331 krb5_error_code ret;
1336 memset(&ref, 0, sizeof(ref));
1338 if (referred_realm) {
1339 ALLOC(ref.referred_realm);
1340 if (ref.referred_realm == NULL)
1342 *ref.referred_realm = strdup(referred_realm);
1343 if (*ref.referred_realm == NULL)
1346 if (true_principal_name) {
1347 ALLOC(ref.true_principal_name);
1348 if (ref.true_principal_name == NULL)
1350 ret = copy_PrincipalName(true_principal_name, ref.true_principal_name);
1354 if (requested_principal) {
1355 ALLOC(ref.requested_principal_name);
1356 if (ref.requested_principal_name == NULL)
1358 ret = copy_PrincipalName(requested_principal,
1359 ref.requested_principal_name);
1364 ASN1_MALLOC_ENCODE(PA_ServerReferralData,
1365 data.data, data.length,
1367 free_PA_ServerReferralData(&ref);
1370 if (data.length != size)
1371 krb5_abortx(context, "internal asn.1 encoder error");
1373 ret = krb5_encrypt_EncryptedData(context, session,
1374 KRB5_KU_PA_SERVER_REFERRAL,
1375 data.data, data.length,
1381 ASN1_MALLOC_ENCODE(EncryptedData,
1382 outdata->data, outdata->length,
1384 free_EncryptedData(&ed);
1387 if (outdata->length != size)
1388 krb5_abortx(context, "internal asn.1 encoder error");
1392 free_PA_ServerReferralData(&ref);
1393 krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
1397 static krb5_error_code
1398 tgs_build_reply(krb5_context context,
1399 krb5_kdc_configuration *config,
1402 hdb_entry_ex *krbtgt,
1403 krb5_enctype krbtgt_etype,
1404 const krb5_keyblock *replykey,
1406 krb5_ticket *ticket,
1409 const char **e_text,
1410 AuthorizationData **auth_data,
1411 const struct sockaddr *from_addr)
1413 krb5_error_code ret;
1414 krb5_principal cp = NULL, sp = NULL;
1415 krb5_principal client_principal = NULL;
1416 char *spn = NULL, *cpn = NULL;
1417 hdb_entry_ex *server = NULL, *client = NULL;
1419 krb5_realm ref_realm = NULL;
1420 EncTicketPart *tgt = &ticket->ticket;
1421 krb5_principals spp = NULL;
1422 const EncryptionKey *ekey;
1423 krb5_keyblock sessionkey;
1427 METHOD_DATA enc_pa_data;
1432 EncTicketPart adtkt;
1438 memset(&sessionkey, 0, sizeof(sessionkey));
1439 memset(&adtkt, 0, sizeof(adtkt));
1440 krb5_data_zero(&rspac);
1441 memset(&enc_pa_data, 0, sizeof(enc_pa_data));
1446 if(b->kdc_options.enc_tkt_in_skey){
1452 if(b->additional_tickets == NULL ||
1453 b->additional_tickets->len == 0){
1454 ret = KRB5KDC_ERR_BADOPTION; /* ? */
1455 kdc_log(context, config, 0,
1456 "No second ticket present in request");
1459 t = &b->additional_tickets->val[0];
1460 if(!get_krbtgt_realm(&t->sname)){
1461 kdc_log(context, config, 0,
1462 "Additional ticket is not a ticket-granting ticket");
1463 ret = KRB5KDC_ERR_POLICY;
1466 _krb5_principalname2krb5_principal(context, &p, t->sname, t->realm);
1467 ret = _kdc_db_fetch(context, config, p,
1468 HDB_F_GET_CLIENT|HDB_F_GET_SERVER,
1470 krb5_free_principal(context, p);
1472 if (ret == HDB_ERR_NOENTRY)
1473 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1476 ret = hdb_enctype2key(context, &uu->entry,
1477 t->enc_part.etype, &uukey);
1479 _kdc_free_ent(context, uu);
1480 ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
1483 ret = krb5_decrypt_ticket(context, t, &uukey->key, &adtkt, 0);
1484 _kdc_free_ent(context, uu);
1488 ret = verify_flags(context, config, &adtkt, spn);
1496 _krb5_principalname2krb5_principal(context, &sp, *s, r);
1497 ret = krb5_unparse_name(context, sp, &spn);
1500 _krb5_principalname2krb5_principal(context, &cp, tgt->cname, tgt->crealm);
1501 ret = krb5_unparse_name(context, cp, &cpn);
1504 unparse_flags (KDCOptions2int(b->kdc_options),
1505 asn1_KDCOptions_units(),
1506 opt_str, sizeof(opt_str));
1508 kdc_log(context, config, 0,
1509 "TGS-REQ %s from %s for %s [%s]",
1510 cpn, from, spn, opt_str);
1512 kdc_log(context, config, 0,
1513 "TGS-REQ %s from %s for %s", cpn, from, spn);
1520 ret = _kdc_db_fetch(context, config, sp, HDB_F_GET_SERVER | HDB_F_CANON,
1524 const char *new_rlm, *msg;
1528 if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) {
1530 new_rlm = find_rpath(context, tgt->crealm, req_rlm);
1532 kdc_log(context, config, 5, "krbtgt for realm %s "
1533 "not found, trying %s",
1535 krb5_free_principal(context, sp);
1537 krb5_make_principal(context, &sp, r,
1538 KRB5_TGS_NAME, new_rlm, NULL);
1539 ret = krb5_unparse_name(context, sp, &spn);
1545 ref_realm = strdup(new_rlm);
1549 } else if(need_referral(context, config, &b->kdc_options, sp, &realms)) {
1550 if (strcmp(realms[0], sp->realm) != 0) {
1551 kdc_log(context, config, 5,
1552 "Returning a referral to realm %s for "
1553 "server %s that was not found",
1555 krb5_free_principal(context, sp);
1557 krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
1559 ret = krb5_unparse_name(context, sp, &spn);
1565 ref_realm = strdup(realms[0]);
1567 krb5_free_host_realm(context, realms);
1570 krb5_free_host_realm(context, realms);
1572 msg = krb5_get_error_message(context, ret);
1573 kdc_log(context, config, 0,
1574 "Server not found in database: %s: %s", spn, msg);
1575 krb5_free_error_message(context, msg);
1576 if (ret == HDB_ERR_NOENTRY)
1577 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1581 ret = _kdc_db_fetch(context, config, cp, HDB_F_GET_CLIENT | HDB_F_CANON,
1582 &clientdb, &client);
1584 const char *krbtgt_realm, *msg;
1587 * If the client belongs to the same realm as our krbtgt, it
1588 * should exist in the local database.
1593 krb5_principal_get_comp_string(context,
1594 krbtgt->entry.principal, 1);
1596 if(strcmp(krb5_principal_get_realm(context, cp), krbtgt_realm) == 0) {
1597 if (ret == HDB_ERR_NOENTRY)
1598 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
1599 kdc_log(context, config, 1, "Client no longer in database: %s",
1604 msg = krb5_get_error_message(context, ret);
1605 kdc_log(context, config, 1, "Client not found in database: %s", msg);
1606 krb5_free_error_message(context, msg);
1610 * Select enctype, return key and kvno.
1616 if(b->kdc_options.enc_tkt_in_skey) {
1619 for(i = 0; i < b->etype.len; i++)
1620 if (b->etype.val[i] == adtkt.key.keytype)
1622 if(i == b->etype.len) {
1623 kdc_log(context, config, 0,
1624 "Addition ticket have not matching etypes");
1625 krb5_clear_error_message(context);
1626 ret = KRB5KDC_ERR_ETYPE_NOSUPP;
1629 etype = b->etype.val[i];
1634 ret = _kdc_find_etype(context, server,
1635 b->etype.val, b->etype.len, &skey);
1637 kdc_log(context, config, 0,
1638 "Server (%s) has no support for etypes", spn);
1642 etype = skey->key.keytype;
1643 kvno = server->entry.kvno;
1646 ret = krb5_generate_random_keyblock(context, etype, &sessionkey);
1652 * Check that service is in the same realm as the krbtgt. If it's
1653 * not the same, it's someone that is using a uni-directional trust
1657 if (strcmp(krb5_principal_get_realm(context, sp),
1658 krb5_principal_get_comp_string(context,
1659 krbtgt->entry.principal,
1662 ret = krb5_unparse_name(context, krbtgt->entry.principal, &tpn);
1663 kdc_log(context, config, 0,
1664 "Request with wrong krbtgt: %s",
1665 (ret == 0) ? tpn : "<unknown>");
1668 ret = KRB5KRB_AP_ERR_NOT_US;
1673 * Validate authoriation data
1676 ret = hdb_enctype2key(context, &krbtgt->entry,
1677 krbtgt_etype, &tkey);
1679 kdc_log(context, config, 0,
1680 "Failed to find key for krbtgt PAC check");
1684 ret = check_PAC(context, config, cp,
1685 client, server, ekey, &tkey->key,
1686 tgt, &rspac, &signedpath);
1688 const char *msg = krb5_get_error_message(context, ret);
1689 kdc_log(context, config, 0,
1690 "Verify PAC failed for %s (%s) from %s with %s",
1691 spn, cpn, from, msg);
1692 krb5_free_error_message(context, msg);
1696 /* also check the krbtgt for signature */
1697 ret = check_KRB5SignedPath(context,
1705 const char *msg = krb5_get_error_message(context, ret);
1706 kdc_log(context, config, 0,
1707 "KRB5SignedPath check failed for %s (%s) from %s with %s",
1708 spn, cpn, from, msg);
1709 krb5_free_error_message(context, msg);
1717 client_principal = cp;
1720 const PA_DATA *sdata;
1723 sdata = _kdc_find_padata(req, &i, KRB5_PADATA_FOR_USER);
1728 char *selfcpn = NULL;
1731 ret = decode_PA_S4U2Self(sdata->padata_value.data,
1732 sdata->padata_value.length,
1735 kdc_log(context, config, 0, "Failed to decode PA-S4U2Self");
1739 ret = _krb5_s4u2self_to_checksumdata(context, &self, &datack);
1743 ret = krb5_crypto_init(context, &tgt->key, 0, &crypto);
1745 const char *msg = krb5_get_error_message(context, ret);
1746 free_PA_S4U2Self(&self);
1747 krb5_data_free(&datack);
1748 kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
1749 krb5_free_error_message(context, msg);
1753 ret = krb5_verify_checksum(context,
1755 KRB5_KU_OTHER_CKSUM,
1759 krb5_data_free(&datack);
1760 krb5_crypto_destroy(context, crypto);
1762 const char *msg = krb5_get_error_message(context, ret);
1763 free_PA_S4U2Self(&self);
1764 kdc_log(context, config, 0,
1765 "krb5_verify_checksum failed for S4U2Self: %s", msg);
1766 krb5_free_error_message(context, msg);
1770 ret = _krb5_principalname2krb5_principal(context,
1774 free_PA_S4U2Self(&self);
1778 ret = krb5_unparse_name(context, client_principal, &selfcpn);
1783 * Check that service doing the impersonating is
1784 * requesting a ticket to it-self.
1786 if (krb5_principal_compare(context, cp, sp) != TRUE) {
1787 kdc_log(context, config, 0, "S4U2Self: %s is not allowed "
1788 "to impersonate some other user "
1789 "(tried for user %s to service %s)",
1792 ret = KRB5KDC_ERR_BADOPTION; /* ? */
1797 * If the service isn't trusted for authentication to
1798 * delegation, remove the forward flag.
1801 if (client->entry.flags.trusted_for_delegation) {
1802 str = "[forwardable]";
1804 b->kdc_options.forwardable = 0;
1807 kdc_log(context, config, 0, "s4u2self %s impersonating %s to "
1808 "service %s %s", cpn, selfcpn, spn, str);
1814 * Constrained delegation
1818 && b->additional_tickets != NULL
1819 && b->additional_tickets->len != 0
1820 && b->kdc_options.enc_tkt_in_skey == 0)
1822 int ad_signedpath = 0;
1828 * Require that the KDC have issued the service's krbtgt (not
1829 * self-issued ticket with kimpersonate(1).
1832 ret = KRB5KDC_ERR_BADOPTION;
1833 kdc_log(context, config, 0,
1834 "Constrained delegation done on service ticket %s/%s",
1839 t = &b->additional_tickets->val[0];
1841 ret = hdb_enctype2key(context, &client->entry,
1842 t->enc_part.etype, &clientkey);
1844 ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
1848 ret = krb5_decrypt_ticket(context, t, &clientkey->key, &adtkt, 0);
1850 kdc_log(context, config, 0,
1851 "failed to decrypt ticket for "
1852 "constrained delegation from %s to %s ", cpn, spn);
1856 /* check that ticket is valid */
1857 if (adtkt.flags.forwardable == 0) {
1858 kdc_log(context, config, 0,
1859 "Missing forwardable flag on ticket for "
1860 "constrained delegation from %s to %s ", cpn, spn);
1861 ret = KRB5KDC_ERR_BADOPTION;
1865 ret = check_constrained_delegation(context, config, clientdb,
1868 kdc_log(context, config, 0,
1869 "constrained delegation from %s to %s not allowed",
1874 ret = _krb5_principalname2krb5_principal(context,
1881 ret = krb5_unparse_name(context, client_principal, &str);
1885 ret = verify_flags(context, config, &adtkt, str);
1892 * Check that the KDC issued the user's ticket.
1894 ret = check_KRB5SignedPath(context,
1901 if (ret == 0 && !ad_signedpath)
1902 ret = KRB5KDC_ERR_BADOPTION;
1904 const char *msg = krb5_get_error_message(context, ret);
1905 kdc_log(context, config, 0,
1906 "KRB5SignedPath check from service %s failed "
1907 "for delegation to %s for client %s "
1908 "from %s failed with %s",
1909 spn, str, cpn, from, msg);
1910 krb5_free_error_message(context, msg);
1915 kdc_log(context, config, 0, "constrained delegation for %s "
1916 "from %s to %s", str, cpn, spn);
1924 ret = kdc_check_flags(context, config,
1931 if((b->kdc_options.validate || b->kdc_options.renew) &&
1932 !krb5_principal_compare(context,
1933 krbtgt->entry.principal,
1934 server->entry.principal)){
1935 kdc_log(context, config, 0, "Inconsistent request.");
1936 ret = KRB5KDC_ERR_SERVER_NOMATCH;
1940 /* check for valid set of addresses */
1941 if(!_kdc_check_addresses(context, config, tgt->caddr, from_addr)) {
1942 ret = KRB5KRB_AP_ERR_BADADDR;
1943 kdc_log(context, config, 0, "Request from wrong address");
1948 * If this is an referral, add server referral data to the
1955 kdc_log(context, config, 0,
1956 "Adding server referral to %s", ref_realm);
1958 ret = krb5_crypto_init(context, &sessionkey, 0, &crypto);
1962 ret = build_server_referral(context, config, crypto, ref_realm,
1963 NULL, s, &pa.padata_value);
1964 krb5_crypto_destroy(context, crypto);
1966 kdc_log(context, config, 0,
1967 "Failed building server referral");
1970 pa.padata_type = KRB5_PADATA_SERVER_REFERRAL;
1972 ret = add_METHOD_DATA(&enc_pa_data, &pa);
1973 krb5_data_free(&pa.padata_value);
1975 kdc_log(context, config, 0,
1976 "Add server referral METHOD-DATA failed");
1985 ret = tgs_make_reply(context,
2013 krb5_data_free(&rspac);
2014 krb5_free_keyblock_contents(context, &sessionkey);
2016 _kdc_free_ent(context, server);
2018 _kdc_free_ent(context, client);
2020 if (client_principal && client_principal != cp)
2021 krb5_free_principal(context, client_principal);
2023 krb5_free_principal(context, cp);
2025 krb5_free_principal(context, sp);
2028 free_METHOD_DATA(&enc_pa_data);
2030 free_EncTicketPart(&adtkt);
2040 _kdc_tgs_rep(krb5_context context,
2041 krb5_kdc_configuration *config,
2045 struct sockaddr *from_addr,
2048 AuthorizationData *auth_data = NULL;
2049 krb5_error_code ret;
2051 const PA_DATA *tgs_req;
2053 hdb_entry_ex *krbtgt = NULL;
2054 krb5_ticket *ticket = NULL;
2055 const char *e_text = NULL;
2056 krb5_enctype krbtgt_etype = ETYPE_NULL;
2058 krb5_keyblock *replykey = NULL;
2059 int rk_is_subkey = 0;
2060 time_t *csec = NULL;
2063 if(req->padata == NULL){
2064 ret = KRB5KDC_ERR_PREAUTH_REQUIRED; /* XXX ??? */
2065 kdc_log(context, config, 0,
2066 "TGS-REQ from %s without PA-DATA", from);
2070 tgs_req = _kdc_find_padata(req, &i, KRB5_PADATA_TGS_REQ);
2072 if(tgs_req == NULL){
2073 ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
2075 kdc_log(context, config, 0,
2076 "TGS-REQ from %s without PA-TGS-REQ", from);
2079 ret = tgs_parse_request(context, config,
2080 &req->req_body, tgs_req,
2091 kdc_log(context, config, 0,
2092 "Failed parsing TGS-REQ from %s", from);
2096 ret = tgs_build_reply(context,
2111 kdc_log(context, config, 0,
2112 "Failed building TGS-REP to %s", from);
2117 if (datagram_reply && data->length > config->max_datagram_reply_length) {
2118 krb5_data_free(data);
2119 ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
2120 e_text = "Reply packet too large";
2125 krb5_free_keyblock(context, replykey);
2126 if(ret && data->data == NULL){
2127 krb5_mk_error(context,
2140 krb5_free_ticket(context, ticket);
2142 _kdc_free_ent(context, krbtgt);
2145 free_AuthorizationData(auth_data);