*** empty log message ***
authorJohn Kohl <jtkohl@mit.edu>
Thu, 3 May 1990 17:33:54 +0000 (17:33 +0000)
committerJohn Kohl <jtkohl@mit.edu>
Thu, 3 May 1990 17:33:54 +0000 (17:33 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@709 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/krb5/krb/walk_rtree.c [new file with mode: 0644]

diff --git a/src/lib/krb5/krb/walk_rtree.c b/src/lib/krb5/krb/walk_rtree.c
new file mode 100644 (file)
index 0000000..9ce3fc0
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * $Source$
+ * $Author$
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <krb5/copyright.h>.
+ *
+ * krb5_walk_realm_tree()
+ */
+
+#if !defined(lint) && !defined(SABER)
+static char rcsid_walk_rtree_c[] =
+"$Id$";
+#endif /* !lint & !SABER */
+
+#include <krb5/copyright.h>
+#include <krb5/krb5.h>
+#include <krb5/krb5_err.h>
+#include <krb5/ext-proto.h>
+#include <errno.h>
+
+/* internal function, used by krb5_get_cred_from_kdc() */
+
+#define REALM_BRANCH_CHAR '.'
+
+#ifndef min
+#define min(x,y) ((x) < (y) ? (x) : (y))
+#define max(x,y) ((x) > (y) ? (x) : (y))
+#endif
+
+krb5_error_code
+krb5_walk_realm_tree(client, server, tree)
+const krb5_principal client, server;
+krb5_principal **tree;
+{
+    krb5_error_code retval;
+    krb5_principal *rettree;
+    register char *ccp, *scp;
+    register char *prevccp, *prevscp;
+    char *com_sdot = 0, *com_cdot = 0;
+    register int i, links = 0;
+    int clen, slen;
+    krb5_data tmpcrealm, tmpsrealm;
+    int nocommon = 1;
+
+    clen = krb5_princ_realm(client)->length;
+    slen = krb5_princ_realm(server)->length;
+
+    for (com_cdot = ccp = krb5_princ_realm(client)->data + clen - 1,
+        com_sdot = scp = krb5_princ_realm(server)->data + slen - 1;
+        clen && slen && *ccp == *scp ;
+        ccp--, scp--,  clen--, slen--) {
+       if (*ccp == REALM_BRANCH_CHAR) {
+           com_cdot = ccp;
+           com_sdot = scp;
+           nocommon = 0;
+       }
+    }
+
+    /* ccp, scp point to common root.
+       com_cdot, com_sdot point to common components. */
+    /* handle case of one ran out */
+    if (!clen) {
+       /* construct path from client to server, down the tree */
+       if (!slen)
+           /* in the same realm--this means there is no ticket
+              in this realm. */
+           return KRB5_NO_TKT_IN_RLM;
+       if (*scp == REALM_BRANCH_CHAR) {
+           /* one is a subdomain of the other */
+           com_cdot = krb5_princ_realm(client)->data;
+           com_sdot = scp;
+       } /* else normal case of two sharing parents */
+    }
+    if (!slen) {
+       /* construct path from client to server, up the tree */
+       if (*ccp == REALM_BRANCH_CHAR) {
+           /* one is a subdomain of the other */
+           com_sdot = krb5_princ_realm(server)->data;
+           com_cdot = ccp;
+       } /* else normal case of two sharing parents */
+    }
+    /* determine #links to/from common ancestor */
+    if (nocommon)
+       links = 1;
+    else
+       links = 2;
+    /* if no common ancestor, artificially set up common root at the last
+       component, then join with special code */
+    for (ccp = krb5_princ_realm(client)->data; ccp < com_cdot; ccp++) {
+       if (*ccp == REALM_BRANCH_CHAR) {
+           links++;
+           if (nocommon)
+               prevccp = ccp;
+       }
+    }
+    if (nocommon)
+       com_cdot = prevccp;
+
+    for (scp = krb5_princ_realm(server)->data; scp < com_sdot; scp++) {
+       if (*scp == REALM_BRANCH_CHAR) {
+           links++;
+           if (nocommon)
+               prevscp = scp;
+       }
+    }
+    if (nocommon)
+       com_sdot = prevscp;
+    if (nocommon && links == 3) {
+       /* no components, and not the same */
+       com_cdot = krb5_princ_realm(client)->data;
+       com_sdot = krb5_princ_realm(server)->data;
+    }
+
+    if (!(rettree = (krb5_principal *)calloc(links+1,
+                                            sizeof(krb5_principal)))) {
+       return ENOMEM;
+    }
+    i = 0;
+    for (prevccp = ccp = krb5_princ_realm(client)->data;
+        ccp <= com_cdot;
+        ccp++) {
+       if (*ccp != REALM_BRANCH_CHAR)
+           continue;
+       ++ccp;                          /* advance past dot */
+       tmpcrealm.data = prevccp;
+       tmpcrealm.length = krb5_princ_realm(client)->length -
+           (prevccp - krb5_princ_realm(client)->data);
+       tmpsrealm.data = ccp;
+       tmpsrealm.length = krb5_princ_realm(client)->length -
+           (ccp - krb5_princ_realm(client)->data);
+       if (retval = krb5_tgtname(&tmpsrealm, &tmpcrealm, &rettree[i])) {
+           while (i) {
+               krb5_free_principal(rettree[i-1]);
+               i--;
+           }
+           xfree(rettree);
+           return retval;
+       }
+       prevccp = ccp;
+       i++;
+    }
+    if (nocommon) {
+       tmpcrealm.data = com_cdot + 1;
+       tmpcrealm.length = krb5_princ_realm(client)->length -
+           (com_cdot + 1 - krb5_princ_realm(client)->data);
+       tmpsrealm.data = com_sdot + 1;
+       tmpsrealm.length = krb5_princ_realm(server)->length -
+           (com_sdot + 1 - krb5_princ_realm(server)->data);
+       if (retval = krb5_tgtname(&tmpsrealm, &tmpcrealm, &rettree[i])) {
+           while (i) {
+               krb5_free_principal(rettree[i-1]);
+               i--;
+           }
+           xfree(rettree);
+           return retval;
+       }
+       i++;
+    }
+
+    for (prevscp = com_sdot + 1, scp = com_sdot - 1;
+        scp > krb5_princ_realm(server)->data;
+        scp--) {
+       if (*scp != REALM_BRANCH_CHAR)
+           continue;
+       if (scp - 1 < krb5_princ_realm(server)->data)
+           break;                      /* XXX only if . starts realm? */
+       tmpcrealm.data = prevscp;
+       tmpcrealm.length = krb5_princ_realm(server)->length -
+           (prevscp - krb5_princ_realm(server)->data);
+       tmpsrealm.data = scp + 1;
+       tmpsrealm.length = krb5_princ_realm(server)->length -
+           (scp + 1 - krb5_princ_realm(server)->data);
+       if (retval = krb5_tgtname(&tmpsrealm, &tmpcrealm, &rettree[i])) {
+           while (i) {
+               krb5_free_principal(rettree[i-1]);
+               i--;
+           }
+           xfree(rettree);
+           return retval;
+       }
+       prevscp = scp + 1;
+       i++;
+    }
+    if (slen) {
+       /* only necessary if building down tree from ancestor or client */
+       tmpcrealm.data = prevscp;
+       tmpcrealm.length = krb5_princ_realm(server)->length -
+           (prevscp - krb5_princ_realm(server)->data);
+       if (retval = krb5_tgtname(krb5_princ_realm(server), &tmpcrealm,
+                                 &rettree[i])) {
+           while (i) {
+               krb5_free_principal(rettree[i-1]);
+               i--;
+           }
+           xfree(rettree);
+           return retval;
+       }
+    }
+    *tree = rettree;
+    return 0;
+}