From 85292848ff3c750868fb86b3c213a0ca2c22b003 Mon Sep 17 00:00:00 2001 From: Theodore Tso Date: Thu, 22 Sep 1994 16:39:53 +0000 Subject: [PATCH] Applied Cybersafe's changes to do transited realm path checking git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@4328 dc483132-0cff-0310-8789-dd5450dbe970 --- src/include/krb5/ChangeLog | 5 + src/include/krb5/func-proto.h | 4 + src/kdc/ChangeLog | 16 ++ src/kdc/do_tgs_req.c | 15 +- src/kdc/kdc_util.c | 298 +++++++++++++++----------- src/kdc/kdc_util.h | 3 +- src/lib/krb5/error_tables/ChangeLog | 4 + src/lib/krb5/error_tables/krb5_err.et | 2 +- src/lib/krb5/krb/ChangeLog | 8 + src/lib/krb5/krb/Makefile.in | 2 + src/lib/krb5/krb/chk_trans.c | 92 ++++++++ src/lib/krb5/krb/rd_req_dec.c | 64 +++++- 12 files changed, 378 insertions(+), 135 deletions(-) create mode 100644 src/lib/krb5/krb/chk_trans.c diff --git a/src/include/krb5/ChangeLog b/src/include/krb5/ChangeLog index 27f5a9f6b..c24eb4065 100644 --- a/src/include/krb5/ChangeLog +++ b/src/include/krb5/ChangeLog @@ -1,3 +1,8 @@ +Wed Sep 21 18:10:55 1994 Theodore Y. Ts'o (tytso@dcl) + + * func_proto.h (krb5_check_transited_list): Added prototype for + function donated by Cybersafe. + Wed Aug 17 16:33:22 1994 Theodore Y. Ts'o (tytso at tsx-11) * krb5.h (krb5_enc_kdc_rep_part): Added msg_type field. Needed diff --git a/src/include/krb5/func-proto.h b/src/include/krb5/func-proto.h index c43a0cc1e..f341a429d 100644 --- a/src/include/krb5/func-proto.h +++ b/src/include/krb5/func-proto.h @@ -233,6 +233,10 @@ char *krb5_cc_default_name krb5_error_code krb5_cc_default PROTOTYPE((krb5_ccache *)); +/* chk_trans.c */ +krb5_error_code krb5_check_transited_list + PROTOTYPE((krb5_data *trans, krb5_data *realm1, krb5_data *realm2)); + /* free_rtree.c */ void krb5_free_realm_tree PROTOTYPE((krb5_principal *)); diff --git a/src/kdc/ChangeLog b/src/kdc/ChangeLog index 8ef51cae7..f07594cd5 100644 --- a/src/kdc/ChangeLog +++ b/src/kdc/ChangeLog @@ -1,3 +1,19 @@ +Wed Sep 21 17:40:56 1994 Theodore Y. Ts'o (tytso@dcl) + + * kdc_util.c, kdc_util.h (realm_compare): Change realm_compare so + that both arguments are principals. This makes it less + confusing.... + + * kdc_util.c (add_to_transited): Folded in Tony Andrea's changes + so that add_to_transited doesn't assume that the contents + of a krb5_data->data are null terminated. + + * do_tgs_req.c (process_tgs_req): Add the realm of the presented + tgt if it is different from the local realm (cross-realm) and it + is different than the realm of the client (since the realm of + the client is already implicitly part of the transited list and + should not be explicitly listed). + Thu Aug 18 18:17:59 1994 Theodore Y. Ts'o (tytso at tsx-11) * configure.in: diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c index 1fcd41a7d..6b46954c8 100644 --- a/src/kdc/do_tgs_req.c +++ b/src/kdc/do_tgs_req.c @@ -422,12 +422,21 @@ tgt_again: enc_tkt_reply.transited.tr_type = KRB5_DOMAIN_X500_COMPRESS; enc_tkt_reply.transited.tr_contents = empty_string; /* equivalent of "" */ + /* + * Only add the realm of the presented tgt to the transited list if + * it is different than the local realm (cross-realm) and it is different + * than the realm of the client (since the realm of the client is already + * implicitly part of the transited list and should not be explicitly + * listed). + */ + /* realm compare is like strcmp, but knows how to deal with these args */ - if (realm_compare(realm_of_tgt(header_ticket), - header_ticket->server)) { - /* tgt issued by local realm */ + if (realm_compare(header_ticket->server, tgs_server) || + realm_compare(header_ticket->server, enc_tkt_reply.client)) { + /* tgt issued by local realm or issued by realm of client */ enc_tkt_reply.transited = header_ticket->enc_part2->transited; } else { + /* tgt issued by some other realm and not the realm of the client */ /* assemble new transited field into allocated storage */ if (header_ticket->enc_part2->transited.tr_type != KRB5_DOMAIN_X500_COMPRESS) { diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c index f3c18fa86..92b99a3c1 100644 --- a/src/kdc/kdc_util.c +++ b/src/kdc/kdc_util.c @@ -91,15 +91,16 @@ krb5_authdata ***output; } krb5_boolean -realm_compare(realmname, princ) -krb5_data *realmname; -krb5_principal princ; +realm_compare(DECLARG(krb5_principal, princ1), + DECLARG(krb5_principal, princ2)) +OLDDECLARG(krb5_principal, princ1) +OLDDECLARG(krb5_principal, princ2) { - if (realmname->length != krb5_princ_realm(princ)->length) - return FALSE; - return(memcmp((char *)realmname->data, - (char *)krb5_princ_realm(princ)->data, - realmname->length) ? FALSE : TRUE); + krb5_data *realm1 = krb5_princ_realm(princ1); + krb5_data *realm2 = krb5_princ_realm(princ2); + + return((realm1->length == realm2->length) && + !memcmp(realm1->data, realm2->data, realm1->length)); } struct kparg { @@ -518,147 +519,188 @@ char *r2; */ krb5_error_code -add_to_transited(tgt_trans,new_trans,tgs,client,server) -krb5_data *tgt_trans; -krb5_data *new_trans; -krb5_principal tgs; -krb5_principal client; -krb5_principal server; +add_to_transited(DECLARG(krb5_data *, tgt_trans), + DECLARG(krb5_data *, new_trans), + DECLARG(krb5_principal, tgs), + DECLARG(krb5_principal, client), + DECLARG(krb5_principal, server)) +OLDDECLARG(krb5_data *, tgt_trans) +OLDDECLARG(krb5_data *, new_trans) +OLDDECLARG(krb5_principal, tgs) +OLDDECLARG(krb5_principal, client) +OLDDECLARG(krb5_principal, server) { - char *realm = (char *)krb5_princ_realm(tgs)->data; - char *trans = (char *)malloc(strlen(realm) + tgt_trans->length + 1); - char *otrans = tgt_trans->data; + char *realm; + char *trans; + char *otrans; - /* The following are for stepping through the transited field */ - char prev[MAX_REALM_LN]; - char next[MAX_REALM_LN]; - char current[MAX_REALM_LN]; - char exp[MAX_REALM_LN]; /* Expanded current realm name */ + /* The following are for stepping through the transited field */ - int retval; - int clst,nlst; /* count of last character in current and next */ - int pl,pl1; /* prefix length */ - int added = 0; /* 1 = new realm has been added */ + char prev[MAX_REALM_LN]; + char next[MAX_REALM_LN]; + char current[MAX_REALM_LN]; + char exp[MAX_REALM_LN]; /* Expanded current realm name */ - if(!trans) return(ENOMEM); + int clst, nlst; /* count of last character in current and next */ + int pl, pl1; /* prefix length */ + int added; /* TRUE = new realm has been added */ - if(new_trans->data) krb5_xfree(new_trans->data); + if (!(realm = (char *) malloc(krb5_princ_realm(tgs)->length+1))) { + return(ENOMEM); + } + memcpy(realm, krb5_princ_realm(tgs)->data, krb5_princ_realm(tgs)->length); + realm[krb5_princ_realm(tgs)->length] = '\0'; - new_trans->data = trans; + if (!(otrans = (char *) malloc(tgt_trans->length+1))) { + return(ENOMEM); + } + memcpy(otrans, tgt_trans->data, tgt_trans->length); + otrans[tgt_trans->length] = '\0'; - /* For the purpose of appending, the realm preceding the first */ - /* relam in the transited field is considered the null realm */ - strcpy(prev,""); + if (!(trans = (char *) malloc(strlen(realm) + strlen(otrans) + 1))) { + return(ENOMEM); + } - /***** In next statement, need to keep reading if the , was quoted *****/ - /* read field into current */ - retval = sscanf(otrans,"%[^,]",current); + if (new_trans->data) free(new_trans->data); + new_trans->data = trans; - if(retval == 1) otrans = otrans + strlen(current); - else *current = '\0'; + /* For the purpose of appending, the realm preceding the first */ + /* realm in the transited field is considered the null realm */ - if(*otrans == ',') otrans++; - - if(strcmp(krb5_princ_realm(client)->data,realm) == 0) - added = 1; + prev[0] = '\0'; - if(strcmp(krb5_princ_realm(server)->data,realm) == 0) - added = 1; + /***** In next statement, need to keep reading if the , was quoted *****/ + /* read field into current */ - while(*current) { + if (sscanf(otrans, "%[^,]", current) == 1) { + otrans += strlen(current); + } + else { + current[0] = '\0'; + } - /* figure out expanded form of current name */ - clst = strlen(current) - 1; - if(current[0] == ' ') { - strcpy(exp,current+1); - } - else if((current[0] == '/') && (prev[0] == '/')) { - strcpy(exp,prev); - strcat(exp,current); - } - else if(current[clst] == '.') { - strcpy(exp,current); - strcat(exp,prev); - } - else strcpy(exp,current); + if (otrans[0] == ',') otrans++; + + added = (krb5_princ_realm(client)->length == strlen(realm) && + !strncmp(krb5_princ_realm(client)->data, realm, strlen(realm))) || + (krb5_princ_realm(server)->length == strlen(realm) && + !strncmp(krb5_princ_realm(server)->data, realm, strlen(realm))); - /***** next statement, need to keep reading if the , was quoted *****/ - /* read field into next */ - retval = sscanf(otrans,"%[^,]",next); + while (current[0]) { - if(retval == 1) { - otrans = otrans + strlen(next); - nlst = strlen(next) - 1; - } - else { - *next = '\0'; - nlst = 0; - } + /* figure out expanded form of current name */ - if(*otrans == ',') otrans++; - - if(strcmp(exp,realm) == 0) added = 1; - - /* If we still have to insert the new realm */ - if(added == 0) { - /* Is the next field compressed? If not, and if the new */ - /* realm is a subrealm of the current realm, compress */ - /* the new realm, and insert immediately following the */ - /* current one. Note that we can not do this if the next*/ - /* field is already compressed since it would mess up */ - /* what has already been done. In most cases, this is */ - /* not a problem becase the realm to be added will be a */ - /* subrealm of the next field too, and we will catch */ - /* it in a future iteration. */ - if((next[nlst] != '.') && (next[0] != '/') && - (pl = subrealm(exp,realm))) { - added = 1; - strcat(current,","); - if(pl > 0) strncat(current,realm,pl); - else strncat(current,realm+strlen(realm)+pl,-pl); - } - /* Whether or not the next field is compressed, if the */ - /* realm to be added is a superrealm of the current realm,*/ - /* then the current realm can be compressed. First the */ - /* realm to be added must be compressed relative to the */ - /* previous realm (if possible), and then the current */ - /* realm compressed relative to the new realm. Note that */ - /* if the realm to be added is also a superrealm of the */ - /* previous realm, it would have been added earlier, and */ - /* we would not reach this step this time around. */ - else if(pl = subrealm(realm,exp)) { - added = 1; - *current = '\0'; - pl1 = subrealm(prev,realm); - if(pl1) { - if(pl1 > 0) strncat(current,realm,pl1); - else strncat(current,realm+strlen(realm)+pl1,-pl1); - } - else { /* If not a subrealm */ - if((realm[0] == '/') && prev[0]) strcat(current," "); - strcat(current,realm); - } - strcat(current,","); - if(pl > 0) strncat(current,exp,pl); - else strncat(current,exp+strlen(exp)+pl,-pl); - } - } + clst = strlen(current) - 1; + if (current[0] == ' ') { + strcpy(exp, current+1); + } + else if ((current[0] == '/') && (prev[0] == '/')) { + strcpy(exp, prev); + strcat(exp, current); + } + else if (current[clst] == '.') { + strcpy(exp, current); + strcat(exp, prev); + } + else { + strcpy(exp, current); + } - if(new_trans->length != 0) strcat(trans,","); - strcat(trans,current); - new_trans->length = strlen(trans) + 1; + /***** next statement, need to keep reading if the , was quoted *****/ + /* read field into next */ - strcpy(prev,exp); - strcpy(current,next); + if (sscanf(otrans, "%[^,]", next) == 1) { + otrans += strlen(next); + nlst = strlen(next) - 1; + } + else { + next[0] = '\0'; + nlst = 0; } - if(added == 0) { - if(new_trans->length != 0) strcat(trans,","); - if((realm[0] == '/') && trans[0]) strcat(trans," "); - strcat(trans,realm); - new_trans->length = strlen(trans) + 1; + if (otrans[0] == ',') otrans++; + + if (!strcmp(exp, realm)) added = TRUE; + + /* If we still have to insert the new realm */ + + if (!added) { + + /* Is the next field compressed? If not, and if the new */ + /* realm is a subrealm of the current realm, compress */ + /* the new realm, and insert immediately following the */ + /* current one. Note that we can not do this if the next*/ + /* field is already compressed since it would mess up */ + /* what has already been done. In most cases, this is */ + /* not a problem because the realm to be added will be a */ + /* subrealm of the next field too, and we will catch */ + /* it in a future iteration. */ + + if ((next[nlst] != '.') && (next[0] != '/') && + (pl = subrealm(exp, realm))) { + added = TRUE; + strcat(current, ","); + if (pl > 0) { + strncat(current, realm, pl); + } + else { + strncat(current, realm+strlen(realm)+pl, -pl); + } + } + + /* Whether or not the next field is compressed, if the */ + /* realm to be added is a superrealm of the current realm,*/ + /* then the current realm can be compressed. First the */ + /* realm to be added must be compressed relative to the */ + /* previous realm (if possible), and then the current */ + /* realm compressed relative to the new realm. Note that */ + /* if the realm to be added is also a superrealm of the */ + /* previous realm, it would have been added earlier, and */ + /* we would not reach this step this time around. */ + + else if (pl = subrealm(realm, exp)) { + added = TRUE; + current[0] = '\0'; + if (pl1 = subrealm(prev,realm)) { + if (pl1 > 0) { + strncat(current, realm, pl1); + } + else { + strncat(current, realm+strlen(realm)+pl1, -pl1); + } + } + else { /* If not a subrealm */ + if ((realm[0] == '/') && prev[0]) { + strcat(current, " "); + } + strcat(current, realm); + } + strcat(current,","); + if (pl > 0) { + strncat(current, exp, pl); + } + else { + strncat(current, exp+strlen(exp)+pl, -pl); + } + } } - return 0; + + if (new_trans->length != 0) strcat(trans, ","); + strcat(trans, current); + new_trans->length = strlen(trans) + 1; + + strcpy(prev, exp); + strcpy(current, next); + } + + if (!added) { + if (new_trans->length != 0) strcat(trans, ","); + if((realm[0] == '/') && trans[0]) strcat(trans, " "); + strcat(trans, realm); + new_trans->length = strlen(trans) + 1; + } + + return(0); } /* diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h index 25b8ffbcb..e2e8e8cbc 100644 --- a/src/kdc/kdc_util.h +++ b/src/kdc/kdc_util.h @@ -29,7 +29,7 @@ #define __KRB5_KDC_UTIL__ krb5_error_code check_hot_list PROTOTYPE((krb5_ticket *)); -krb5_boolean realm_compare PROTOTYPE((krb5_data *, krb5_principal)); +krb5_boolean realm_compare PROTOTYPE((krb5_principal, krb5_principal)); krb5_boolean krb5_is_tgs_principal PROTOTYPE((krb5_principal)); krb5_error_code add_to_transited PROTOTYPE((krb5_data *, krb5_data *, @@ -91,7 +91,6 @@ void kdc_insert_lookaside PROTOTYPE((krb5_data *, krb5_data *)); #define setflag(flagfield, flag) (flagfield |= (flag)) #define clear(flagfield, flag) (flagfield &= ~(flag)) -#define realm_of_tgt(ticket) krb5_princ_realm(ticket->server) #ifdef KRB4 krb5_error_code process_v4 PROTOTYPE((const krb5_data *, const krb5_fulladdr *, diff --git a/src/lib/krb5/error_tables/ChangeLog b/src/lib/krb5/error_tables/ChangeLog index cf1076271..f0740c3a4 100644 --- a/src/lib/krb5/error_tables/ChangeLog +++ b/src/lib/krb5/error_tables/ChangeLog @@ -1,3 +1,7 @@ +Wed Sep 21 18:00:25 1994 Theodore Y. Ts'o (tytso@dcl) + + * krb5_err.et (KRB5KRB_AP_ERR_ILL_CR_TKT): Added new error code. + Sat Jul 16 05:59:53 1994 Tom Yu (tlyu at dragons-lair) * krb5_err.et: missing space between comma and doublequote diff --git a/src/lib/krb5/error_tables/krb5_err.et b/src/lib/krb5/error_tables/krb5_err.et index 1201b7e3b..133814c3a 100644 --- a/src/lib/krb5/error_tables/krb5_err.et +++ b/src/lib/krb5/error_tables/krb5_err.et @@ -74,7 +74,7 @@ error_code KRB5KRB_AP_ERR_BADVERSION, "Protocol version mismatch" error_code KRB5KRB_AP_ERR_MSG_TYPE, "Invalid message type" error_code KRB5KRB_AP_ERR_MODIFIED, "Message stream modified" error_code KRB5KRB_AP_ERR_BADORDER, "Message out of order" -error_code KRB5PLACEHOLD_43, "KRB5 error code 43" +error_code KRB5KRB_AP_ERR_ILL_CR_TKT, "Illegal cross-realm ticket" error_code KRB5KRB_AP_ERR_BADKEYVER, "Key version is not available" error_code KRB5KRB_AP_ERR_NOKEY, "Service key not available" error_code KRB5KRB_AP_ERR_MUT_FAIL, "Mutual authentication failed" diff --git a/src/lib/krb5/krb/ChangeLog b/src/lib/krb5/krb/ChangeLog index 9afcfe98d..665d800e2 100644 --- a/src/lib/krb5/krb/ChangeLog +++ b/src/lib/krb5/krb/ChangeLog @@ -1,3 +1,11 @@ +Wed Sep 21 17:57:35 1994 Theodore Y. Ts'o (tytso@dcl) + + * rd_req_dec.c (krb5_rd_req_decoded): Added Changes from Cybersafe + to do transited realm path checking. + + * chk_trans.c: Added donated module from CyberSafe. It checks to + see if a transited path is a legal one between two realms. + Thu Sep 15 11:08:39 1994 Theodore Y. Ts'o (tytso@dcl) * rd_req_sim.c (krb5_rd_req_simple): Use krb5_rd_req instead of diff --git a/src/lib/krb5/krb/Makefile.in b/src/lib/krb5/krb/Makefile.in index 2570abcb4..d647f1e12 100644 --- a/src/lib/krb5/krb/Makefile.in +++ b/src/lib/krb5/krb/Makefile.in @@ -10,6 +10,7 @@ OBJS= addr_comp.o \ addr_srch.o \ bld_pr_ext.o \ bld_princ.o \ + chk_trans.o \ compat_recv.o \ conv_princ.o \ copy_addrs.o \ @@ -69,6 +70,7 @@ SRCS= $(srcdir)/addr_comp.c \ $(srcdir)/addr_srch.c \ $(srcdir)/bld_pr_ext.c \ $(srcdir)/bld_princ.c \ + $(srcdir/chk_trans.c \ $(srcdir)/compat_recv.c \ $(srcdir)/conv_princ.c \ $(srcdir)/copy_addrs.c \ diff --git a/src/lib/krb5/krb/chk_trans.c b/src/lib/krb5/krb/chk_trans.c new file mode 100644 index 000000000..e4c06dd1d --- /dev/null +++ b/src/lib/krb5/krb/chk_trans.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 1994 CyberSAFE Corporation. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Neither M.I.T., the Open Computing Security Group, nor + * CyberSAFE Corporation make any representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include + +#define MAX_REALM_LN 500 + +krb5_error_code krb5_check_transited_list(trans, realm1, realm2) +krb5_data *trans; +krb5_data *realm1; +krb5_data *realm2; +{ + char prev[MAX_REALM_LN+1]; + char next[MAX_REALM_LN+1]; + char *nextp; + int i, j; + int trans_length; + krb5_error_code retval = 0; + krb5_principal *tgs_list; + + if (!trans || !trans->data) return(0); + trans_length = trans->data[trans->length-1] ? + trans->length : trans->length - 1; + + if (retval = krb5_walk_realm_tree(realm1, realm2, &tgs_list, + KRB5_REALM_BRANCH_CHAR)) { + return(retval); + } + + memset(prev, 0, MAX_REALM_LN + 1); + memset(next, 0, MAX_REALM_LN + 1), nextp = next; + for (i = 0; i <= trans_length; i++) { + if (i < trans_length-1 && trans->data[i] == '\\') { + i++; + *nextp++ = trans->data[i]; + continue; + } + if (i < trans_length && trans->data[i] != ',') { + *nextp++ = trans->data[i]; + continue; + } + if (strlen(next) > 0) { + if (next[0] != '/') { + if (*(nextp-1) == '.') strcat(next, prev); + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + for (j = 0; tgs_list[j]; j++) { + if (strlen(next) == krb5_princ_realm(tgs_list[j])->length && + !memcmp(next, krb5_princ_realm(tgs_list[j])->data, + strlen(next))) { + retval = 0; + break; + } + } + if (retval) goto finish; + } + if (i+1 < trans_length && trans->data[i+1] == ' ') { + i++; + memset(next, 0, MAX_REALM_LN + 1), nextp = next; + continue; + } + if (i+1 < trans_length && trans->data[i+1] != '/') { + strcpy(prev, next); + memset(next, 0, MAX_REALM_LN + 1), nextp = next; + continue; + } + } + } + +finish: + krb5_free_realm_tree(tgs_list); + return(retval); +} diff --git a/src/lib/krb5/krb/rd_req_dec.c b/src/lib/krb5/krb/rd_req_dec.c index 694a48dbc..12a47742e 100644 --- a/src/lib/krb5/krb/rd_req_dec.c +++ b/src/lib/krb5/krb/rd_req_dec.c @@ -1,6 +1,7 @@ /* * lib/krb5/krb/rd_req_dec.c * + * Copyright (c) 1994 CyberSAFE Corporation. * Copyright 1990,1991 by the Massachusetts Institute of Technology. * All Rights Reserved. * @@ -16,7 +17,8 @@ * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior - * permission. M.I.T. makes no representations about the suitability of + * permission. Neither M.I.T., the Open Computing Security Group, nor + * CyberSAFE Corporation make any representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * @@ -164,6 +166,66 @@ krb5_tkt_authent **authdat; goto cleanup; } + /* okay, now check cross-realm policy */ + +#if defined(_SINGLE_HOP_ONLY) + + /* Single hop cross-realm tickets only */ + + { krb5_transited *trans = &(req->ticket->enc_part2->transited); + + /* If the transited list is empty, then we have at most one hop */ + + if (trans->tr_contents.data && trans->tr_contents.data[0]) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + } + } + +#elif defined(_NO_CROSS_REALM) + + /* No cross-realm tickets */ + + { char *lrealm; + krb5_data *realm = krb5_princ_realm(req->ticket->enc_part2->client); + krb5_transited *trans = &(req->ticket->enc_part2->transited); + + /* If the transited list is empty, then we have at most one hop */ + /* So we also have to check that the client's realm is the local one */ + + krb5_get_default_realm(&lrealm); + if ((trans->tr_contents.data && trans->tr_contents.data[0]) || + strlen(lrealm) != realm->length || + memcmp(lrealm, realm->data, strlen(lrealm))) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + } + free(lrealm); + } + +#else + + /* Hierarchical Cross-Realm */ + + { int i; + krb5_data lrealm; + krb5_data *realm = krb5_princ_realm(req->ticket->enc_part2->client); + krb5_transited *trans = &(req->ticket->enc_part2->transited); + + /* If the transited list is not empty, then check that all realms */ + /* transited are within the hierarchy between the client's realm */ + /* and the local realm. */ + + if (trans->tr_contents.data && trans->tr_contents.data[0]) { + krb5_get_default_realm(&(lrealm.data)); + lrealm.length = strlen(lrealm.data); + retval = krb5_check_transited_list(&(trans->tr_contents), realm, + &lrealm); + free(lrealm.data); + } + } + +#endif + + if (retval) goto cleanup; /* only check rcache if sender has provided one---some services may not be able to use replay caches (such as datagram servers) */ -- 2.26.2