Applied Cybersafe's changes to do transited realm path checking
authorTheodore Tso <tytso@mit.edu>
Thu, 22 Sep 1994 16:39:53 +0000 (16:39 +0000)
committerTheodore Tso <tytso@mit.edu>
Thu, 22 Sep 1994 16:39:53 +0000 (16:39 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@4328 dc483132-0cff-0310-8789-dd5450dbe970

12 files changed:
src/include/krb5/ChangeLog
src/include/krb5/func-proto.h
src/kdc/ChangeLog
src/kdc/do_tgs_req.c
src/kdc/kdc_util.c
src/kdc/kdc_util.h
src/lib/krb5/error_tables/ChangeLog
src/lib/krb5/error_tables/krb5_err.et
src/lib/krb5/krb/ChangeLog
src/lib/krb5/krb/Makefile.in
src/lib/krb5/krb/chk_trans.c [new file with mode: 0644]
src/lib/krb5/krb/rd_req_dec.c

index 27f5a9f6baeb07fdc809f68ad0b89f3a38750220..c24eb4065b47119d5c62180223f541e010a1558b 100644 (file)
@@ -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
index c43a0cc1e4f0b55bd6eec8363d68a67cff47254e..f341a429dfce6ccd5c948192f59f9a6e7b5c67b8 100644 (file)
@@ -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 *));
index 8ef51cae7887568028ad65bb3e480bb2f2c4943a..f07594cd5270ff64789b99daa28030e690b8b8ef 100644 (file)
@@ -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:
index 1fcd41a7db673809439619b403a138bcafdd1803..6b46954c863927cdf2fe0c8ba47ffb5c80e4ec7a 100644 (file)
@@ -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) {
index f3c18fa869ab0f6027dde56dcdcdc671a12c6a58..92b99a3c14035cdd9931a0722d440ff1d8d1621b 100644 (file)
@@ -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);
 }
 
 /*
index 25b8ffbcb8b42a1955f951388ec55ea53d55d9c5..e2e8e8cbc9ef0e6a18b089d7f6f7a55a2465581c 100644 (file)
@@ -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 *,
index cf1076271d08fc30ee5bf49d207591d6e83b7151..f0740c3a4694c4e072c9a0cc544483c917c4ff72 100644 (file)
@@ -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
index 1201b7e3becc0c7189f7a87ce8c28594b91b9a91..133814c3a7fe5ffe0d736dcfed5760be10cb178f 100644 (file)
@@ -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"
index 9afcfe98d4f9799a9b4906d8971ce43841223719..665d800e2ef7e47ac8aecc6e054288076ec417ba 100644 (file)
@@ -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
index 2570abcb474496bfb4273369da15060d1aea7a37..d647f1e128594ff65c58274d0735176fcd2bf26e 100644 (file)
@@ -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 (file)
index 0000000..e4c06dd
--- /dev/null
@@ -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 <stdio.h>
+#include <krb5/krb5.h>
+
+#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);
+}
index 694a48dbc06b17df658090d0a9f86e9623478915..12a47742ef97852f206769357ee73499404c2952 100644 (file)
@@ -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) */