xref: /illumos-gate/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/walk_rtree.c (revision fe598cdcd847f8359013532d5c691bb6190378c0)
17c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
27c478bd9Sstevel@tonic-gate /*
37c478bd9Sstevel@tonic-gate  * lib/krb5/krb/walk_rtree.c
47c478bd9Sstevel@tonic-gate  *
57c478bd9Sstevel@tonic-gate  * Copyright 1990,1991 by the Massachusetts Institute of Technology.
67c478bd9Sstevel@tonic-gate  * All Rights Reserved.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
97c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
107c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
117c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
147c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
157c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
167c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
177c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
187c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
197c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
207c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
217c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
227c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
237c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
247c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
257c478bd9Sstevel@tonic-gate  * or implied warranty.
267c478bd9Sstevel@tonic-gate  *
277c478bd9Sstevel@tonic-gate  *
287c478bd9Sstevel@tonic-gate  * krb5_walk_realm_tree()
297c478bd9Sstevel@tonic-gate  */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate /* ANL - Modified to allow Configurable Authentication Paths.
327c478bd9Sstevel@tonic-gate  * This modification removes the restriction on the choice of realm
337c478bd9Sstevel@tonic-gate  * names, i.e. they nolonger have to be hierarchical. This
347c478bd9Sstevel@tonic-gate  * is allowed by RFC 1510: "If a hierarchical orginization is not used
357c478bd9Sstevel@tonic-gate  * it may be necessary to consult some database in order to construct
367c478bd9Sstevel@tonic-gate  * an authentication path between realms."  The database is contained
37*fe598cdcSmp153739  * in the [capaths] section of the krb5.conf file.
387c478bd9Sstevel@tonic-gate  * Client to server paths are defined. There are n**2 possible
397c478bd9Sstevel@tonic-gate  * entries, but only those entries which are needed by the client
407c478bd9Sstevel@tonic-gate  * or server need be present in its krb5.conf file. (n entries or 2*n
417c478bd9Sstevel@tonic-gate  * entries if the same krb5.conf is used for clients and servers)
427c478bd9Sstevel@tonic-gate  *
437c478bd9Sstevel@tonic-gate  * for example: ESnet will be running a KDC which will share
447c478bd9Sstevel@tonic-gate  * inter-realm keys with its many orginizations which include among
457c478bd9Sstevel@tonic-gate  * other ANL, NERSC and PNL. Each of these orginizations wants to
467c478bd9Sstevel@tonic-gate  * use its DNS name in the realm, ANL.GOV. In addition ANL wants
477c478bd9Sstevel@tonic-gate  * to authenticatite to HAL.COM via a K5.MOON and K5.JUPITER
48*fe598cdcSmp153739  * A [capaths] section of the krb5.conf file for the ANL.GOV clients
497c478bd9Sstevel@tonic-gate  * and servers would look like:
507c478bd9Sstevel@tonic-gate  *
51*fe598cdcSmp153739  * [capaths]
527c478bd9Sstevel@tonic-gate  * ANL.GOV = {
537c478bd9Sstevel@tonic-gate  *		NERSC.GOV = ES.NET
547c478bd9Sstevel@tonic-gate  *		PNL.GOV = ES.NET
557c478bd9Sstevel@tonic-gate  *		ES.NET = .
567c478bd9Sstevel@tonic-gate  * 		HAL.COM = K5.MOON
577c478bd9Sstevel@tonic-gate  * 		HAL.COM = K5.JUPITER
587c478bd9Sstevel@tonic-gate  * }
597c478bd9Sstevel@tonic-gate  * NERSC.GOV = {
607c478bd9Sstevel@tonic-gate  *		ANL.GOV = ES.NET
617c478bd9Sstevel@tonic-gate  * }
627c478bd9Sstevel@tonic-gate  * PNL.GOV = {
637c478bd9Sstevel@tonic-gate  *		ANL.GOV = ES.NET
647c478bd9Sstevel@tonic-gate  * }
657c478bd9Sstevel@tonic-gate  * ES.NET = {
667c478bd9Sstevel@tonic-gate  * 		ANL.GOV = .
677c478bd9Sstevel@tonic-gate  * }
687c478bd9Sstevel@tonic-gate  * HAL.COM = {
697c478bd9Sstevel@tonic-gate  *		ANL.GOV = K5.JUPITER
707c478bd9Sstevel@tonic-gate  *		ANL.GOV = K5.MOON
717c478bd9Sstevel@tonic-gate  * }
727c478bd9Sstevel@tonic-gate  *
737c478bd9Sstevel@tonic-gate  * In the above a "." is used to mean directly connected since the
747c478bd9Sstevel@tonic-gate  * the profile routines cannot handle a null entry.
757c478bd9Sstevel@tonic-gate  *
767c478bd9Sstevel@tonic-gate  * If no client-to-server path is found, the default hierarchical path
777c478bd9Sstevel@tonic-gate  * is still generated.
787c478bd9Sstevel@tonic-gate  *
797c478bd9Sstevel@tonic-gate  * This version of the Configurable Authentication Path modification
807c478bd9Sstevel@tonic-gate  * differs from the previous versions prior to K5 beta 5 in that
817c478bd9Sstevel@tonic-gate  * the profile routines are used, and the explicite path from
827c478bd9Sstevel@tonic-gate  * client's realm to server's realm must be given. The modifications
837c478bd9Sstevel@tonic-gate  * will work together.
847c478bd9Sstevel@tonic-gate  * DEE - 5/23/95
857c478bd9Sstevel@tonic-gate  */
867c478bd9Sstevel@tonic-gate #define CONFIGURABLE_AUTHENTICATION_PATH
877c478bd9Sstevel@tonic-gate #include "k5-int.h"
887c478bd9Sstevel@tonic-gate #include "int-proto.h"
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate /* internal function, used by krb5_get_cred_from_kdc() */
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate #ifndef min
937c478bd9Sstevel@tonic-gate #define min(x,y) ((x) < (y) ? (x) : (y))
947c478bd9Sstevel@tonic-gate #define max(x,y) ((x) > (y) ? (x) : (y))
957c478bd9Sstevel@tonic-gate #endif
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate /*
987c478bd9Sstevel@tonic-gate  * xxx The following function is very confusing to read and probably
997c478bd9Sstevel@tonic-gate  * is buggy.  It should be documented better.  Here is what I've
1007c478bd9Sstevel@tonic-gate  * learned about it doing a quick bug fixing walk through.  The
1017c478bd9Sstevel@tonic-gate  * function takes a client and server realm name and returns the set
1027c478bd9Sstevel@tonic-gate  * of realms (in a field called tree) that you need to get tickets in
1037c478bd9Sstevel@tonic-gate  * in order to get from the source realm to the destination realm.  It
1047c478bd9Sstevel@tonic-gate  * takes a realm separater character (normally ., but presumably there
1057c478bd9Sstevel@tonic-gate  * for all those X.500 realms) .  There are two modes it runs in: the
1067c478bd9Sstevel@tonic-gate  * ANL krb5.conf mode and the hierarchy mode.  The ANL mode is
1077c478bd9Sstevel@tonic-gate  * fairly obvious.  The hierarchy mode looks for common components in
1087c478bd9Sstevel@tonic-gate  * both the client and server realms.  In general, the pointer scp and
1097c478bd9Sstevel@tonic-gate  * ccp are used to walk through the client and server realms.  The
1107c478bd9Sstevel@tonic-gate  * com_sdot and com_cdot pointers point to (I think) the beginning of
1117c478bd9Sstevel@tonic-gate  * the common part of the realm names.  I.E. strcmp(com_cdot,
1127c478bd9Sstevel@tonic-gate  * com_sdot) ==0 is roughly an invarient.  However, there are cases
1137c478bd9Sstevel@tonic-gate  * where com_sdot and com_cdot are set to point before the start of
1147c478bd9Sstevel@tonic-gate  * the client or server strings.  I think this only happens when there
1157c478bd9Sstevel@tonic-gate  * are no common components.  --hartmans 2002/03/14
1167c478bd9Sstevel@tonic-gate  */
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate krb5_error_code
119*fe598cdcSmp153739 krb5_walk_realm_tree(krb5_context context, const krb5_data *client, const krb5_data *server, krb5_principal **tree, int realm_branch_char)
1207c478bd9Sstevel@tonic-gate {
1217c478bd9Sstevel@tonic-gate     krb5_error_code retval;
1227c478bd9Sstevel@tonic-gate     krb5_principal *rettree;
1237c478bd9Sstevel@tonic-gate     register char *ccp, *scp;
1247c478bd9Sstevel@tonic-gate     register char *prevccp = 0, *prevscp = 0;
1257c478bd9Sstevel@tonic-gate     char *com_sdot = 0, *com_cdot = 0;
1267c478bd9Sstevel@tonic-gate     register int i, links = 0;
127*fe598cdcSmp153739     int clen, slen = -1;
1287c478bd9Sstevel@tonic-gate     krb5_data tmpcrealm, tmpsrealm;
1297c478bd9Sstevel@tonic-gate     int nocommon = 1;
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate #ifdef CONFIGURABLE_AUTHENTICATION_PATH
1327c478bd9Sstevel@tonic-gate     const char *cap_names[4];
1337c478bd9Sstevel@tonic-gate     char *cap_client, *cap_server;
1347c478bd9Sstevel@tonic-gate     char **cap_nodes;
1357c478bd9Sstevel@tonic-gate     krb5_error_code cap_code;
1367c478bd9Sstevel@tonic-gate #endif
137*fe598cdcSmp153739 
138*fe598cdcSmp153739 #ifdef DEBUG_REFERRALS
139*fe598cdcSmp153739     printf("krb5_walk_realm_tree starting\n");
140*fe598cdcSmp153739     printf("  client is %s\n",client->data);
141*fe598cdcSmp153739     printf("  server is %s\n",server->data);
142*fe598cdcSmp153739 #endif
143*fe598cdcSmp153739 
1447c478bd9Sstevel@tonic-gate     if (!(client->data &&server->data))
1457c478bd9Sstevel@tonic-gate       return KRB5_NO_TKT_IN_RLM;
1467c478bd9Sstevel@tonic-gate #ifdef CONFIGURABLE_AUTHENTICATION_PATH
1477c478bd9Sstevel@tonic-gate     if ((cap_client = (char *)malloc(client->length + 1)) == NULL)
1487c478bd9Sstevel@tonic-gate 	return ENOMEM;
1497c478bd9Sstevel@tonic-gate     strncpy(cap_client, client->data, client->length);
1507c478bd9Sstevel@tonic-gate     cap_client[client->length] = '\0';
1517c478bd9Sstevel@tonic-gate     if ((cap_server = (char *)malloc(server->length + 1)) == NULL) {
1527c478bd9Sstevel@tonic-gate 	krb5_xfree(cap_client);
1537c478bd9Sstevel@tonic-gate 	return ENOMEM;
1547c478bd9Sstevel@tonic-gate     }
1557c478bd9Sstevel@tonic-gate     strncpy(cap_server, server->data, server->length);
1567c478bd9Sstevel@tonic-gate     cap_server[server->length] = '\0';
1577c478bd9Sstevel@tonic-gate     cap_names[0] = "capaths";
1587c478bd9Sstevel@tonic-gate     cap_names[1] = cap_client;
1597c478bd9Sstevel@tonic-gate     cap_names[2] = cap_server;
1607c478bd9Sstevel@tonic-gate     cap_names[3] = 0;
1617c478bd9Sstevel@tonic-gate     cap_code = profile_get_values(context->profile, cap_names, &cap_nodes);
162*fe598cdcSmp153739     krb5_xfree(cap_client);  /* done with client string */
163*fe598cdcSmp153739     cap_names[1] = 0;
1647c478bd9Sstevel@tonic-gate     if (cap_code == 0) {     /* found a path, so lets use it */
1657c478bd9Sstevel@tonic-gate 	links = 0;
1667c478bd9Sstevel@tonic-gate 	if (*cap_nodes[0] != '.') { /* a link of . means direct */
1677c478bd9Sstevel@tonic-gate 	    while(cap_nodes[links]) {
1687c478bd9Sstevel@tonic-gate 		links++;
1697c478bd9Sstevel@tonic-gate 	    }
1707c478bd9Sstevel@tonic-gate 	}
171*fe598cdcSmp153739 	if (cap_nodes[links] != NULL)
172*fe598cdcSmp153739 	    krb5_xfree(cap_nodes[links]);
173*fe598cdcSmp153739 
1747c478bd9Sstevel@tonic-gate 	cap_nodes[links] = cap_server; /* put server on end of list */
1757c478bd9Sstevel@tonic-gate 	/* this simplifies the code later and make */
1767c478bd9Sstevel@tonic-gate 	/* cleanup eaiser as well */
1777c478bd9Sstevel@tonic-gate 	links++;		/* count the null entry at end */
1787c478bd9Sstevel@tonic-gate     } else {			/* no path use hierarchical method */
179*fe598cdcSmp153739 	krb5_xfree(cap_server); /* failed, don't need server string */
180*fe598cdcSmp153739 	cap_names[2] = 0;
1817c478bd9Sstevel@tonic-gate #endif
1827c478bd9Sstevel@tonic-gate 	clen = client->length;
1837c478bd9Sstevel@tonic-gate 	slen = server->length;
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 	for (com_cdot = ccp = client->data + clen - 1,
1867c478bd9Sstevel@tonic-gate 		 com_sdot = scp = server->data + slen - 1;
1877c478bd9Sstevel@tonic-gate 	     clen && slen && *ccp == *scp ;
1887c478bd9Sstevel@tonic-gate 	     ccp--, scp--, 	clen--, slen--) {
1897c478bd9Sstevel@tonic-gate 	    if (*ccp == realm_branch_char) {
1907c478bd9Sstevel@tonic-gate 		com_cdot = ccp;
1917c478bd9Sstevel@tonic-gate 		com_sdot = scp;
1927c478bd9Sstevel@tonic-gate 		nocommon = 0;
1937c478bd9Sstevel@tonic-gate 	    }
1947c478bd9Sstevel@tonic-gate 	}
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 	/* ccp, scp point to common root.
1977c478bd9Sstevel@tonic-gate 	   com_cdot, com_sdot point to common components. */
1987c478bd9Sstevel@tonic-gate 	/* handle case of one ran out */
1997c478bd9Sstevel@tonic-gate 	if (!clen) {
2007c478bd9Sstevel@tonic-gate 	    /* construct path from client to server, down the tree */
2017c478bd9Sstevel@tonic-gate 	    if (!slen)
2027c478bd9Sstevel@tonic-gate 		/* in the same realm--this means there is no ticket
2037c478bd9Sstevel@tonic-gate 		   in this realm. */
2047c478bd9Sstevel@tonic-gate 		return KRB5_NO_TKT_IN_RLM;
2057c478bd9Sstevel@tonic-gate 	    if (*scp == realm_branch_char) {
2067c478bd9Sstevel@tonic-gate 		/* one is a subdomain of the other */
2077c478bd9Sstevel@tonic-gate 		com_cdot = client->data;
2087c478bd9Sstevel@tonic-gate 		com_sdot = scp;
2097c478bd9Sstevel@tonic-gate 		nocommon = 0;
2107c478bd9Sstevel@tonic-gate 	    } /* else normal case of two sharing parents */
2117c478bd9Sstevel@tonic-gate 	}
2127c478bd9Sstevel@tonic-gate 	if (!slen) {
2137c478bd9Sstevel@tonic-gate 	    /* construct path from client to server, up the tree */
2147c478bd9Sstevel@tonic-gate 	    if (*ccp == realm_branch_char) {
2157c478bd9Sstevel@tonic-gate 		/* one is a subdomain of the other */
2167c478bd9Sstevel@tonic-gate 		com_sdot = server->data;
2177c478bd9Sstevel@tonic-gate 		com_cdot = ccp;
2187c478bd9Sstevel@tonic-gate 		nocommon = 0;
2197c478bd9Sstevel@tonic-gate 	    } /* else normal case of two sharing parents */
2207c478bd9Sstevel@tonic-gate 	}
2217c478bd9Sstevel@tonic-gate 	/* determine #links to/from common ancestor */
2227c478bd9Sstevel@tonic-gate 	if (nocommon)
2237c478bd9Sstevel@tonic-gate 	    links = 1;
2247c478bd9Sstevel@tonic-gate 	else
2257c478bd9Sstevel@tonic-gate 	    links = 2;
2267c478bd9Sstevel@tonic-gate 	/* if no common ancestor, artificially set up common root at the last
2277c478bd9Sstevel@tonic-gate 	   component, then join with special code */
2287c478bd9Sstevel@tonic-gate 	for (ccp = client->data; ccp < com_cdot; ccp++) {
2297c478bd9Sstevel@tonic-gate 	    if (*ccp == realm_branch_char) {
2307c478bd9Sstevel@tonic-gate 		links++;
2317c478bd9Sstevel@tonic-gate 		if (nocommon)
2327c478bd9Sstevel@tonic-gate 		    prevccp = ccp;
2337c478bd9Sstevel@tonic-gate 	    }
2347c478bd9Sstevel@tonic-gate 	}
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 	for (scp = server->data; scp < com_sdot; scp++) {
2377c478bd9Sstevel@tonic-gate 	    if (*scp == realm_branch_char) {
2387c478bd9Sstevel@tonic-gate 		links++;
2397c478bd9Sstevel@tonic-gate 		if (nocommon)
2407c478bd9Sstevel@tonic-gate 		    prevscp = scp;
2417c478bd9Sstevel@tonic-gate 	    }
2427c478bd9Sstevel@tonic-gate 	}
2437c478bd9Sstevel@tonic-gate 	if (nocommon) {
2447c478bd9Sstevel@tonic-gate 	    if (prevccp)
2457c478bd9Sstevel@tonic-gate 		com_cdot = prevccp;
2467c478bd9Sstevel@tonic-gate 	    if (prevscp)
2477c478bd9Sstevel@tonic-gate 		com_sdot = prevscp;
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate 	    if(com_cdot == client->data + client->length -1)
2507c478bd9Sstevel@tonic-gate 		com_cdot = client->data - 1 ;
2517c478bd9Sstevel@tonic-gate 	    if(com_sdot == server->data + server->length -1)
2527c478bd9Sstevel@tonic-gate 		com_sdot = server->data - 1 ;
2537c478bd9Sstevel@tonic-gate 	}
2547c478bd9Sstevel@tonic-gate #ifdef CONFIGURABLE_AUTHENTICATION_PATH
2557c478bd9Sstevel@tonic-gate     }		/* end of if use hierarchical method */
2567c478bd9Sstevel@tonic-gate #endif
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate     if (!(rettree = (krb5_principal *)calloc(links+2,
2597c478bd9Sstevel@tonic-gate 					     sizeof(krb5_principal)))) {
2607c478bd9Sstevel@tonic-gate 	return ENOMEM;
2617c478bd9Sstevel@tonic-gate     }
2627c478bd9Sstevel@tonic-gate     i = 1;
2637c478bd9Sstevel@tonic-gate     if ((retval = krb5_tgtname(context, client, client, &rettree[0]))) {
2647c478bd9Sstevel@tonic-gate 	krb5_xfree(rettree);
2657c478bd9Sstevel@tonic-gate 	return retval;
2667c478bd9Sstevel@tonic-gate     }
2677c478bd9Sstevel@tonic-gate #ifdef CONFIGURABLE_AUTHENTICATION_PATH
2687c478bd9Sstevel@tonic-gate     links--;				/* dont count the null entry on end */
2697c478bd9Sstevel@tonic-gate     if (cap_code == 0) {    /* found a path above */
2707c478bd9Sstevel@tonic-gate 	tmpcrealm.data = client->data;
2717c478bd9Sstevel@tonic-gate 	tmpcrealm.length = client->length;
2727c478bd9Sstevel@tonic-gate 	while( i-1 <= links) {
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	    tmpsrealm.data = cap_nodes[i-1];
2757c478bd9Sstevel@tonic-gate 	    /* don't count trailing whitespace from profile_get */
2767c478bd9Sstevel@tonic-gate 	    tmpsrealm.length = strcspn(cap_nodes[i-1],"\t ");
2777c478bd9Sstevel@tonic-gate 	    if ((retval = krb5_tgtname(context,
2787c478bd9Sstevel@tonic-gate 				       &tmpsrealm,
2797c478bd9Sstevel@tonic-gate 				       &tmpcrealm,
2807c478bd9Sstevel@tonic-gate 				       &rettree[i]))) {
2817c478bd9Sstevel@tonic-gate 		while (i) {
2827c478bd9Sstevel@tonic-gate 		    krb5_free_principal(context, rettree[i-1]);
2837c478bd9Sstevel@tonic-gate 		    i--;
2847c478bd9Sstevel@tonic-gate 		}
2857c478bd9Sstevel@tonic-gate 		krb5_xfree(rettree);
2867c478bd9Sstevel@tonic-gate 				/* cleanup the cap_nodes from profile_get */
2877c478bd9Sstevel@tonic-gate 		for (i = 0; i<=links; i++) {
2887c478bd9Sstevel@tonic-gate 		    krb5_xfree(cap_nodes[i]);
2897c478bd9Sstevel@tonic-gate 		}
2907c478bd9Sstevel@tonic-gate 		krb5_xfree((char *)cap_nodes);
2917c478bd9Sstevel@tonic-gate 		return retval;
2927c478bd9Sstevel@tonic-gate 	    }
2937c478bd9Sstevel@tonic-gate 	    tmpcrealm.data = tmpsrealm.data;
2947c478bd9Sstevel@tonic-gate 	    tmpcrealm.length = tmpsrealm.length;
2957c478bd9Sstevel@tonic-gate 	    i++;
2967c478bd9Sstevel@tonic-gate 	}
2977c478bd9Sstevel@tonic-gate 	/* cleanup the cap_nodes from profile_get last one has server */
2987c478bd9Sstevel@tonic-gate 	for (i = 0; i<=links; i++) {
2997c478bd9Sstevel@tonic-gate 	    krb5_xfree(cap_nodes[i]);
3007c478bd9Sstevel@tonic-gate 	}
3017c478bd9Sstevel@tonic-gate 	krb5_xfree((char *)cap_nodes);
3027c478bd9Sstevel@tonic-gate     } else {  /* if not cap then use hierarchical method */
3037c478bd9Sstevel@tonic-gate #endif
3047c478bd9Sstevel@tonic-gate 	for (prevccp = ccp = client->data;
3057c478bd9Sstevel@tonic-gate 	     ccp <= com_cdot;
3067c478bd9Sstevel@tonic-gate 	     ccp++) {
3077c478bd9Sstevel@tonic-gate 	    if (*ccp != realm_branch_char)
3087c478bd9Sstevel@tonic-gate 		continue;
3097c478bd9Sstevel@tonic-gate 	    ++ccp;				/* advance past dot */
3107c478bd9Sstevel@tonic-gate 	    tmpcrealm.data = prevccp;
3117c478bd9Sstevel@tonic-gate 	    tmpcrealm.length = client->length -
3127c478bd9Sstevel@tonic-gate 		(prevccp - client->data);
3137c478bd9Sstevel@tonic-gate 	    tmpsrealm.data = ccp;
3147c478bd9Sstevel@tonic-gate 	    tmpsrealm.length = client->length -
3157c478bd9Sstevel@tonic-gate 		(ccp - client->data);
3167c478bd9Sstevel@tonic-gate 	    if ((retval = krb5_tgtname(context, &tmpsrealm, &tmpcrealm,
3177c478bd9Sstevel@tonic-gate 				       &rettree[i]))) {
3187c478bd9Sstevel@tonic-gate 		while (i) {
3197c478bd9Sstevel@tonic-gate 		    krb5_free_principal(context, rettree[i-1]);
3207c478bd9Sstevel@tonic-gate 		    i--;
3217c478bd9Sstevel@tonic-gate 		}
3227c478bd9Sstevel@tonic-gate 		krb5_xfree(rettree);
3237c478bd9Sstevel@tonic-gate 		return retval;
3247c478bd9Sstevel@tonic-gate 	    }
3257c478bd9Sstevel@tonic-gate 	    prevccp = ccp;
3267c478bd9Sstevel@tonic-gate 	    i++;
3277c478bd9Sstevel@tonic-gate 	}
3287c478bd9Sstevel@tonic-gate 	if (nocommon) {
3297c478bd9Sstevel@tonic-gate 	    tmpcrealm.data = com_cdot + 1;
3307c478bd9Sstevel@tonic-gate 	    tmpcrealm.length = client->length -
3317c478bd9Sstevel@tonic-gate 		(com_cdot + 1 - client->data);
3327c478bd9Sstevel@tonic-gate 	    tmpsrealm.data = com_sdot + 1;
3337c478bd9Sstevel@tonic-gate 	    tmpsrealm.length = server->length -
3347c478bd9Sstevel@tonic-gate 		(com_sdot + 1 - server->data);
3357c478bd9Sstevel@tonic-gate 	    if ((retval = krb5_tgtname(context, &tmpsrealm, &tmpcrealm,
3367c478bd9Sstevel@tonic-gate 				       &rettree[i]))) {
3377c478bd9Sstevel@tonic-gate 		while (i) {
3387c478bd9Sstevel@tonic-gate 		    krb5_free_principal(context, rettree[i-1]);
3397c478bd9Sstevel@tonic-gate 		    i--;
3407c478bd9Sstevel@tonic-gate 		}
3417c478bd9Sstevel@tonic-gate 		krb5_xfree(rettree);
3427c478bd9Sstevel@tonic-gate 		return retval;
3437c478bd9Sstevel@tonic-gate 	    }
3447c478bd9Sstevel@tonic-gate 	    i++;
3457c478bd9Sstevel@tonic-gate 	}
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 	for (prevscp = com_sdot + 1, scp = com_sdot - 1;
3487c478bd9Sstevel@tonic-gate 	     scp > server->data;
3497c478bd9Sstevel@tonic-gate 	     scp--) {
3507c478bd9Sstevel@tonic-gate 	    if (*scp != realm_branch_char)
3517c478bd9Sstevel@tonic-gate 		continue;
3527c478bd9Sstevel@tonic-gate 	    if (scp - 1 < server->data)
3537c478bd9Sstevel@tonic-gate 		break;			/* XXX only if . starts realm? */
3547c478bd9Sstevel@tonic-gate 	    tmpcrealm.data = prevscp;
3557c478bd9Sstevel@tonic-gate 	    tmpcrealm.length = server->length -
3567c478bd9Sstevel@tonic-gate 		(prevscp - server->data);
3577c478bd9Sstevel@tonic-gate 	    tmpsrealm.data = scp + 1;
3587c478bd9Sstevel@tonic-gate 	    tmpsrealm.length = server->length -
3597c478bd9Sstevel@tonic-gate 		(scp + 1 - server->data);
3607c478bd9Sstevel@tonic-gate 	    if ((retval = krb5_tgtname(context, &tmpsrealm, &tmpcrealm,
3617c478bd9Sstevel@tonic-gate 				       &rettree[i]))) {
3627c478bd9Sstevel@tonic-gate 		while (i) {
3637c478bd9Sstevel@tonic-gate 		    krb5_free_principal(context, rettree[i-1]);
3647c478bd9Sstevel@tonic-gate 		    i--;
3657c478bd9Sstevel@tonic-gate 		}
3667c478bd9Sstevel@tonic-gate 		krb5_xfree(rettree);
3677c478bd9Sstevel@tonic-gate 		return retval;
3687c478bd9Sstevel@tonic-gate 	    }
3697c478bd9Sstevel@tonic-gate 	    prevscp = scp + 1;
3707c478bd9Sstevel@tonic-gate 	    i++;
3717c478bd9Sstevel@tonic-gate 	}
3727c478bd9Sstevel@tonic-gate 	if (slen && com_sdot >= server->data) {
3737c478bd9Sstevel@tonic-gate 	    /* only necessary if building down tree from ancestor or client */
3747c478bd9Sstevel@tonic-gate 	    /* however, we can get here if we have only one component
3757c478bd9Sstevel@tonic-gate 	       in the server realm name, hence we make sure we found a component
3767c478bd9Sstevel@tonic-gate 	       separator there... */
3777c478bd9Sstevel@tonic-gate 	    tmpcrealm.data = prevscp;
3787c478bd9Sstevel@tonic-gate 	    tmpcrealm.length = server->length -
3797c478bd9Sstevel@tonic-gate 		(prevscp - server->data);
3807c478bd9Sstevel@tonic-gate 	    if ((retval = krb5_tgtname(context, server, &tmpcrealm,
3817c478bd9Sstevel@tonic-gate 				       &rettree[i]))) {
3827c478bd9Sstevel@tonic-gate 		while (i) {
3837c478bd9Sstevel@tonic-gate 		    krb5_free_principal(context, rettree[i-1]);
3847c478bd9Sstevel@tonic-gate 		    i--;
3857c478bd9Sstevel@tonic-gate 		}
3867c478bd9Sstevel@tonic-gate 		krb5_xfree(rettree);
3877c478bd9Sstevel@tonic-gate 		return retval;
3887c478bd9Sstevel@tonic-gate 	    }
3897c478bd9Sstevel@tonic-gate 	}
3907c478bd9Sstevel@tonic-gate #ifdef CONFIGURABLE_AUTHENTICATION_PATH
3917c478bd9Sstevel@tonic-gate     }
3927c478bd9Sstevel@tonic-gate #endif
3937c478bd9Sstevel@tonic-gate     *tree = rettree;
394*fe598cdcSmp153739 
395*fe598cdcSmp153739 #ifdef DEBUG_REFERRALS
396*fe598cdcSmp153739     printf("krb5_walk_realm_tree ending; tree (length %d) is:\n",links);
397*fe598cdcSmp153739     for(i=0;i<links+2;i++) {
398*fe598cdcSmp153739         if ((*tree)[i])
399*fe598cdcSmp153739 	    krb5int_dbgref_dump_principal("krb5_walk_realm_tree tree",(*tree)[i]);
400*fe598cdcSmp153739 	else
401*fe598cdcSmp153739 	    printf("tree element %i null\n");
402*fe598cdcSmp153739     }
403*fe598cdcSmp153739 #endif
4047c478bd9Sstevel@tonic-gate     return 0;
4057c478bd9Sstevel@tonic-gate }
406*fe598cdcSmp153739 
407*fe598cdcSmp153739 #ifdef DEBUG_REFERRALS
408*fe598cdcSmp153739 void krb5int_dbgref_dump_principal(char *d, krb5_principal p)
409*fe598cdcSmp153739 {
410*fe598cdcSmp153739     int n;
411*fe598cdcSmp153739 
412*fe598cdcSmp153739     printf("  **%s: ",d);
413*fe598cdcSmp153739     for (n=0;n<p->length;n++)
414*fe598cdcSmp153739 	printf("%s<%.*s>",(n>0)?"/":"",p->data[n].length,p->data[n].data);
415*fe598cdcSmp153739     printf("@<%.*s>  (length %d, type %d)\n",p->realm.length,p->realm.data,
416*fe598cdcSmp153739 	   p->length, p->type);
417*fe598cdcSmp153739 }
418*fe598cdcSmp153739 #endif
419