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