17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * lib/krb5/krb/chk_trans.c
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * Copyright 2001 by the Massachusetts Institute of Technology.
57c478bd9Sstevel@tonic-gate  * All Rights Reserved.
67c478bd9Sstevel@tonic-gate  *
77c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
87c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
97c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
107c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
117c478bd9Sstevel@tonic-gate  *
127c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
137c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
147c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
157c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
167c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
177c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
187c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
197c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
207c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
217c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
227c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
237c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
247c478bd9Sstevel@tonic-gate  * or implied warranty.
257c478bd9Sstevel@tonic-gate  *
267c478bd9Sstevel@tonic-gate  *
277c478bd9Sstevel@tonic-gate  * krb5_check_transited_list()
287c478bd9Sstevel@tonic-gate  */
29*159d09a2SMark Phalan #include "k5-int.h"
307c478bd9Sstevel@tonic-gate #include <stdarg.h>
317c478bd9Sstevel@tonic-gate 
32*159d09a2SMark Phalan #if defined (TEST) || defined (TEST2)
33*159d09a2SMark Phalan # undef DEBUG
34*159d09a2SMark Phalan # define DEBUG
35*159d09a2SMark Phalan #endif
36*159d09a2SMark Phalan 
37*159d09a2SMark Phalan #ifdef DEBUG
38*159d09a2SMark Phalan #define verbose krb5int_chk_trans_verbose
39*159d09a2SMark Phalan static int verbose = 0;
40*159d09a2SMark Phalan # define Tprintf(ARGS) if (verbose) printf ARGS
41*159d09a2SMark Phalan #else
42*159d09a2SMark Phalan # define Tprintf(ARGS) (void)(0)
43*159d09a2SMark Phalan #endif
44*159d09a2SMark Phalan 
457c478bd9Sstevel@tonic-gate #define MAXLEN 512
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate static krb5_error_code
487c478bd9Sstevel@tonic-gate process_intermediates (krb5_error_code (*fn)(krb5_data *, void *), void *data,
497c478bd9Sstevel@tonic-gate 		       const krb5_data *n1, const krb5_data *n2) {
507c478bd9Sstevel@tonic-gate     unsigned int len1, len2, i;
517c478bd9Sstevel@tonic-gate     char *p1, *p2;
527c478bd9Sstevel@tonic-gate 
53*159d09a2SMark Phalan     Tprintf (("process_intermediates(%.*s,%.*s)\n",
54*159d09a2SMark Phalan 	      (int) n1->length, n1->data, (int) n2->length, n2->data));
55*159d09a2SMark Phalan 
567c478bd9Sstevel@tonic-gate     len1 = n1->length;
577c478bd9Sstevel@tonic-gate     len2 = n2->length;
587c478bd9Sstevel@tonic-gate 
59*159d09a2SMark Phalan     Tprintf (("(walking intermediates now)\n"));
607c478bd9Sstevel@tonic-gate     /* Simplify...  */
617c478bd9Sstevel@tonic-gate     if (len1 > len2) {
627c478bd9Sstevel@tonic-gate 	const krb5_data *p;
637c478bd9Sstevel@tonic-gate 	int tmp = len1;
647c478bd9Sstevel@tonic-gate 	len1 = len2;
657c478bd9Sstevel@tonic-gate 	len2 = tmp;
667c478bd9Sstevel@tonic-gate 	p = n1;
677c478bd9Sstevel@tonic-gate 	n1 = n2;
687c478bd9Sstevel@tonic-gate 	n2 = p;
697c478bd9Sstevel@tonic-gate     }
707c478bd9Sstevel@tonic-gate     /* Okay, now len1 is always shorter or equal.  */
717c478bd9Sstevel@tonic-gate     if (len1 == len2) {
727c478bd9Sstevel@tonic-gate 	if (memcmp (n1->data, n2->data, len1)) {
73*159d09a2SMark Phalan 	    Tprintf (("equal length but different strings in path: '%.*s' '%.*s'\n",
74*159d09a2SMark Phalan 		      (int) n1->length, n1->data, (int) n2->length, n2->data));
757c478bd9Sstevel@tonic-gate 	    return KRB5KRB_AP_ERR_ILL_CR_TKT;
767c478bd9Sstevel@tonic-gate 	}
77*159d09a2SMark Phalan 	Tprintf (("(end intermediates)\n"));
787c478bd9Sstevel@tonic-gate 	return 0;
797c478bd9Sstevel@tonic-gate     }
807c478bd9Sstevel@tonic-gate     /* Now len1 is always shorter.  */
817c478bd9Sstevel@tonic-gate     if (len1 == 0)
827c478bd9Sstevel@tonic-gate 	/* Shouldn't be possible.  Internal error?  */
837c478bd9Sstevel@tonic-gate 	return KRB5KRB_AP_ERR_ILL_CR_TKT;
847c478bd9Sstevel@tonic-gate     p1 = n1->data;
857c478bd9Sstevel@tonic-gate     p2 = n2->data;
867c478bd9Sstevel@tonic-gate     if (p1[0] == '/') {
877c478bd9Sstevel@tonic-gate 	/* X.500 style names, with common prefix.  */
887c478bd9Sstevel@tonic-gate 	if (p2[0] != '/') {
89*159d09a2SMark Phalan 	    Tprintf (("mixed name formats in path: x500='%.*s' domain='%.*s'\n",
90*159d09a2SMark Phalan 		      (int) len1, p1, (int) len2, p2));
917c478bd9Sstevel@tonic-gate 	    return KRB5KRB_AP_ERR_ILL_CR_TKT;
927c478bd9Sstevel@tonic-gate 	}
937c478bd9Sstevel@tonic-gate 	if (memcmp (p1, p2, len1)) {
94*159d09a2SMark Phalan 	    Tprintf (("x500 names with different prefixes '%.*s' '%.*s'\n",
95*159d09a2SMark Phalan 		      (int) len1, p1, (int) len2, p2));
967c478bd9Sstevel@tonic-gate 	    return KRB5KRB_AP_ERR_ILL_CR_TKT;
977c478bd9Sstevel@tonic-gate 	}
987c478bd9Sstevel@tonic-gate 	for (i = len1 + 1; i < len2; i++)
997c478bd9Sstevel@tonic-gate 	    if (p2[i] == '/') {
1007c478bd9Sstevel@tonic-gate 		krb5_data d;
1017c478bd9Sstevel@tonic-gate 		krb5_error_code r;
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate 		d.data = p2;
1047c478bd9Sstevel@tonic-gate 		d.length = i;
1057c478bd9Sstevel@tonic-gate 		r = (*fn) (&d, data);
1067c478bd9Sstevel@tonic-gate 		if (r)
1077c478bd9Sstevel@tonic-gate 		    return r;
1087c478bd9Sstevel@tonic-gate 	    }
1097c478bd9Sstevel@tonic-gate     } else {
1107c478bd9Sstevel@tonic-gate 	/* Domain style names, with common suffix.  */
1117c478bd9Sstevel@tonic-gate 	if (p2[0] == '/') {
112*159d09a2SMark Phalan 	    Tprintf (("mixed name formats in path: domain='%.*s' x500='%.*s'\n",
113*159d09a2SMark Phalan 		      (int) len1, p1, (int) len2, p2));
1147c478bd9Sstevel@tonic-gate 	    return KRB5KRB_AP_ERR_ILL_CR_TKT;
1157c478bd9Sstevel@tonic-gate 	}
1167c478bd9Sstevel@tonic-gate 	if (memcmp (p1, p2 + (len2 - len1), len1)) {
117*159d09a2SMark Phalan 	    Tprintf (("domain names with different suffixes '%.*s' '%.*s'\n",
118*159d09a2SMark Phalan 		      (int) len1, p1, (int) len2, p2));
1197c478bd9Sstevel@tonic-gate 	    return KRB5KRB_AP_ERR_ILL_CR_TKT;
1207c478bd9Sstevel@tonic-gate 	}
1217c478bd9Sstevel@tonic-gate 	for (i = len2 - len1 - 1; i > 0; i--) {
122*159d09a2SMark Phalan 	    Tprintf (("looking at '%.*s'\n", (int) (len2 - i), p2+i));
1237c478bd9Sstevel@tonic-gate 	    if (p2[i-1] == '.') {
1247c478bd9Sstevel@tonic-gate 		krb5_data d;
1257c478bd9Sstevel@tonic-gate 		krb5_error_code r;
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 		d.data = p2+i;
1287c478bd9Sstevel@tonic-gate 		d.length = len2 - i;
1297c478bd9Sstevel@tonic-gate 		r = (*fn) (&d, data);
1307c478bd9Sstevel@tonic-gate 		if (r)
1317c478bd9Sstevel@tonic-gate 		    return r;
1327c478bd9Sstevel@tonic-gate 	    }
1337c478bd9Sstevel@tonic-gate 	}
1347c478bd9Sstevel@tonic-gate     }
135*159d09a2SMark Phalan     Tprintf (("(end intermediates)\n"));
1367c478bd9Sstevel@tonic-gate     return 0;
1377c478bd9Sstevel@tonic-gate }
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate static krb5_error_code
1407c478bd9Sstevel@tonic-gate maybe_join (krb5_data *last, krb5_data *buf, int bufsiz)
1417c478bd9Sstevel@tonic-gate {
1427c478bd9Sstevel@tonic-gate     if (buf->length == 0)
1437c478bd9Sstevel@tonic-gate 	return 0;
1447c478bd9Sstevel@tonic-gate     if (buf->data[0] == '/') {
1457c478bd9Sstevel@tonic-gate 	if (last->length + buf->length > bufsiz) {
146*159d09a2SMark Phalan 	    Tprintf (("too big: last=%d cur=%d max=%d\n", last->length, buf->length, bufsiz));
1477c478bd9Sstevel@tonic-gate 	    return KRB5KRB_AP_ERR_ILL_CR_TKT;
1487c478bd9Sstevel@tonic-gate 	}
1497c478bd9Sstevel@tonic-gate 	memmove (buf->data+last->length, buf->data, buf->length);
1507c478bd9Sstevel@tonic-gate 	memcpy (buf->data, last->data, last->length);
1517c478bd9Sstevel@tonic-gate 	buf->length += last->length;
1527c478bd9Sstevel@tonic-gate     } else if (buf->data[buf->length-1] == '.') {
1537c478bd9Sstevel@tonic-gate 	/* We can ignore the case where the previous component was
1547c478bd9Sstevel@tonic-gate 	   empty; the strcat will be a no-op.  It should probably
1557c478bd9Sstevel@tonic-gate 	   be an error case, but let's be flexible.  */
1567c478bd9Sstevel@tonic-gate 	if (last->length+buf->length > bufsiz) {
157*159d09a2SMark Phalan 	    Tprintf (("too big\n"));
1587c478bd9Sstevel@tonic-gate 	    return KRB5KRB_AP_ERR_ILL_CR_TKT;
1597c478bd9Sstevel@tonic-gate 	}
1607c478bd9Sstevel@tonic-gate 	memcpy (buf->data + buf->length, last->data, last->length);
1617c478bd9Sstevel@tonic-gate 	buf->length += last->length;
1627c478bd9Sstevel@tonic-gate     }
1637c478bd9Sstevel@tonic-gate     /* Otherwise, do nothing.  */
1647c478bd9Sstevel@tonic-gate     return 0;
1657c478bd9Sstevel@tonic-gate }
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate /* The input strings cannot contain any \0 bytes, according to the
1687c478bd9Sstevel@tonic-gate    spec, but our API is such that they may not be \0 terminated
1697c478bd9Sstevel@tonic-gate    either.  Thus we keep on treating them as krb5_data objects instead
1707c478bd9Sstevel@tonic-gate    of C strings.  */
1717c478bd9Sstevel@tonic-gate static krb5_error_code
1727c478bd9Sstevel@tonic-gate foreach_realm (krb5_error_code (*fn)(krb5_data *comp,void *data), void *data,
1737c478bd9Sstevel@tonic-gate 	       const krb5_data *crealm, const krb5_data *srealm,
1747c478bd9Sstevel@tonic-gate 	       const krb5_data *transit)
1757c478bd9Sstevel@tonic-gate {
1767c478bd9Sstevel@tonic-gate     char buf[MAXLEN], last[MAXLEN];
1777c478bd9Sstevel@tonic-gate     char *p, *bufp;
1787c478bd9Sstevel@tonic-gate     int next_lit, intermediates, l;
1797c478bd9Sstevel@tonic-gate     krb5_data this_component;
1807c478bd9Sstevel@tonic-gate     krb5_error_code r;
1817c478bd9Sstevel@tonic-gate     krb5_data last_component;
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate     /* Invariants:
1847c478bd9Sstevel@tonic-gate        - last_component points to last[]
1857c478bd9Sstevel@tonic-gate        - this_component points to buf[]
1867c478bd9Sstevel@tonic-gate        - last_component has length of last
1877c478bd9Sstevel@tonic-gate        - this_component has length of buf when calling out
1887c478bd9Sstevel@tonic-gate        Keep these consistent, and we should be okay.  */
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate     next_lit = 0;
1917c478bd9Sstevel@tonic-gate     intermediates = 0;
1927c478bd9Sstevel@tonic-gate     memset (buf, 0, sizeof (buf));
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate     this_component.data = buf;
1957c478bd9Sstevel@tonic-gate     last_component.data = last;
1967c478bd9Sstevel@tonic-gate     last_component.length = 0;
1977c478bd9Sstevel@tonic-gate 
198*159d09a2SMark Phalan #define print_data(fmt,d) Tprintf((fmt,(int)(d)->length,(d)->data))
199*159d09a2SMark Phalan     print_data ("client realm: %.*s\n", crealm);
200*159d09a2SMark Phalan     print_data ("server realm: %.*s\n", srealm);
201*159d09a2SMark Phalan     print_data ("transit enc.: %.*s\n", transit);
202*159d09a2SMark Phalan 
2037c478bd9Sstevel@tonic-gate     if (transit->length == 0) {
204*159d09a2SMark Phalan 	Tprintf (("no other realms transited\n"));
2057c478bd9Sstevel@tonic-gate 	return 0;
2067c478bd9Sstevel@tonic-gate     }
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate     bufp = buf;
2097c478bd9Sstevel@tonic-gate     for (p = transit->data, l = transit->length; l; p++, l--) {
2107c478bd9Sstevel@tonic-gate 	if (next_lit) {
2117c478bd9Sstevel@tonic-gate 	    *bufp++ = *p;
2127c478bd9Sstevel@tonic-gate 	    if (bufp == buf+sizeof(buf))
2137c478bd9Sstevel@tonic-gate 		return KRB5KRB_AP_ERR_ILL_CR_TKT;
2147c478bd9Sstevel@tonic-gate 	    next_lit = 0;
2157c478bd9Sstevel@tonic-gate 	} else if (*p == '\\') {
2167c478bd9Sstevel@tonic-gate 	    next_lit = 1;
2177c478bd9Sstevel@tonic-gate 	} else if (*p == ',') {
2187c478bd9Sstevel@tonic-gate 	    if (bufp != buf) {
2197c478bd9Sstevel@tonic-gate 		this_component.length = bufp - buf;
2207c478bd9Sstevel@tonic-gate 		r = maybe_join (&last_component, &this_component, sizeof(buf));
2217c478bd9Sstevel@tonic-gate 		if (r)
2227c478bd9Sstevel@tonic-gate 		    return r;
2237c478bd9Sstevel@tonic-gate 		r = (*fn) (&this_component, data);
2247c478bd9Sstevel@tonic-gate 		if (r)
2257c478bd9Sstevel@tonic-gate 		    return r;
2267c478bd9Sstevel@tonic-gate 		if (intermediates) {
2277c478bd9Sstevel@tonic-gate 		    if (p == transit->data)
2287c478bd9Sstevel@tonic-gate 			r = process_intermediates (fn, data,
2297c478bd9Sstevel@tonic-gate 						   &this_component, crealm);
2307c478bd9Sstevel@tonic-gate 		    else {
2317c478bd9Sstevel@tonic-gate 			r = process_intermediates (fn, data, &this_component,
2327c478bd9Sstevel@tonic-gate 						   &last_component);
2337c478bd9Sstevel@tonic-gate 		    }
2347c478bd9Sstevel@tonic-gate 		    if (r)
2357c478bd9Sstevel@tonic-gate 			return r;
2367c478bd9Sstevel@tonic-gate 		}
2377c478bd9Sstevel@tonic-gate 		intermediates = 0;
2387c478bd9Sstevel@tonic-gate 		memcpy (last, buf, sizeof (buf));
2397c478bd9Sstevel@tonic-gate 		last_component.length = this_component.length;
2407c478bd9Sstevel@tonic-gate 		memset (buf, 0, sizeof (buf));
2417c478bd9Sstevel@tonic-gate 		bufp = buf;
2427c478bd9Sstevel@tonic-gate 	    } else {
2437c478bd9Sstevel@tonic-gate 		intermediates = 1;
2447c478bd9Sstevel@tonic-gate 		if (p == transit->data) {
2457c478bd9Sstevel@tonic-gate 		    if (crealm->length >= MAXLEN)
2467c478bd9Sstevel@tonic-gate 			return KRB5KRB_AP_ERR_ILL_CR_TKT;
2477c478bd9Sstevel@tonic-gate 		    memcpy (last, crealm->data, crealm->length);
2487c478bd9Sstevel@tonic-gate 		    last[crealm->length] = '\0';
2497c478bd9Sstevel@tonic-gate 		    last_component.length = crealm->length;
2507c478bd9Sstevel@tonic-gate 		}
2517c478bd9Sstevel@tonic-gate 	    }
2527c478bd9Sstevel@tonic-gate 	} else if (*p == ' ' && bufp == buf) {
2537c478bd9Sstevel@tonic-gate 	    /* This next component stands alone, even if it has a
2547c478bd9Sstevel@tonic-gate 	       trailing dot or leading slash.  */
2557c478bd9Sstevel@tonic-gate 	    memset (last, 0, sizeof (last));
2567c478bd9Sstevel@tonic-gate 	    last_component.length = 0;
2577c478bd9Sstevel@tonic-gate 	} else {
2587c478bd9Sstevel@tonic-gate 	    /* Not a special character; literal.  */
2597c478bd9Sstevel@tonic-gate 	    *bufp++ = *p;
2607c478bd9Sstevel@tonic-gate 	    if (bufp == buf+sizeof(buf))
2617c478bd9Sstevel@tonic-gate 		return KRB5KRB_AP_ERR_ILL_CR_TKT;
2627c478bd9Sstevel@tonic-gate 	}
2637c478bd9Sstevel@tonic-gate     }
2647c478bd9Sstevel@tonic-gate     /* At end.  Must be normal state.  */
265*159d09a2SMark Phalan     if (next_lit)
266*159d09a2SMark Phalan 	Tprintf (("ending in next-char-literal state\n"));
2677c478bd9Sstevel@tonic-gate     /* Process trailing element or comma.  */
2687c478bd9Sstevel@tonic-gate     if (bufp == buf) {
2697c478bd9Sstevel@tonic-gate 	/* Trailing comma.  */
2707c478bd9Sstevel@tonic-gate 	r = process_intermediates (fn, data, &last_component, srealm);
2717c478bd9Sstevel@tonic-gate     } else {
2727c478bd9Sstevel@tonic-gate 	/* Trailing component.  */
2737c478bd9Sstevel@tonic-gate 	this_component.length = bufp - buf;
2747c478bd9Sstevel@tonic-gate 	r = maybe_join (&last_component, &this_component, sizeof(buf));
2757c478bd9Sstevel@tonic-gate 	if (r)
2767c478bd9Sstevel@tonic-gate 	    return r;
2777c478bd9Sstevel@tonic-gate 	r = (*fn) (&this_component, data);
2787c478bd9Sstevel@tonic-gate 	if (r)
2797c478bd9Sstevel@tonic-gate 	    return r;
2807c478bd9Sstevel@tonic-gate 	if (intermediates)
2817c478bd9Sstevel@tonic-gate 	    r = process_intermediates (fn, data, &this_component,
2827c478bd9Sstevel@tonic-gate 				       &last_component);
2837c478bd9Sstevel@tonic-gate     }
2847c478bd9Sstevel@tonic-gate     if (r != 0)
2857c478bd9Sstevel@tonic-gate 	return r;
2867c478bd9Sstevel@tonic-gate     return 0;
2877c478bd9Sstevel@tonic-gate }
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate struct check_data {
2917c478bd9Sstevel@tonic-gate     krb5_context ctx;
2927c478bd9Sstevel@tonic-gate     krb5_principal *tgs;
2937c478bd9Sstevel@tonic-gate };
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate static int
2967c478bd9Sstevel@tonic-gate same_data (krb5_data *d1, krb5_data *d2)
2977c478bd9Sstevel@tonic-gate {
2987c478bd9Sstevel@tonic-gate     return (d1->length == d2->length
2997c478bd9Sstevel@tonic-gate 	    && !memcmp (d1->data, d2->data, d1->length));
3007c478bd9Sstevel@tonic-gate }
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate static krb5_error_code
3037c478bd9Sstevel@tonic-gate check_realm_in_list (krb5_data *realm, void *data)
3047c478bd9Sstevel@tonic-gate {
3057c478bd9Sstevel@tonic-gate     struct check_data *cdata = data;
3067c478bd9Sstevel@tonic-gate     int i;
3077c478bd9Sstevel@tonic-gate 
308*159d09a2SMark Phalan     Tprintf ((".. checking '%.*s'\n", (int) realm->length, realm->data));
3097c478bd9Sstevel@tonic-gate     for (i = 0; cdata->tgs[i]; i++) {
3107c478bd9Sstevel@tonic-gate 	if (same_data (krb5_princ_realm (cdata->ctx, cdata->tgs[i]), realm))
3117c478bd9Sstevel@tonic-gate 	    return 0;
3127c478bd9Sstevel@tonic-gate     }
313*159d09a2SMark Phalan     Tprintf (("BAD!\n"));
3147c478bd9Sstevel@tonic-gate     return KRB5KRB_AP_ERR_ILL_CR_TKT;
3157c478bd9Sstevel@tonic-gate }
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate krb5_error_code
318505d05c7Sgtb krb5_check_transited_list (krb5_context ctx, const krb5_data *trans_in,
3197c478bd9Sstevel@tonic-gate 			   const krb5_data *crealm, const krb5_data *srealm)
3207c478bd9Sstevel@tonic-gate {
3217c478bd9Sstevel@tonic-gate     krb5_data trans;
3227c478bd9Sstevel@tonic-gate     struct check_data cdata;
3237c478bd9Sstevel@tonic-gate     krb5_error_code r;
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate     trans.length = trans_in->length;
3267c478bd9Sstevel@tonic-gate     trans.data = (char *) trans_in->data;
3277c478bd9Sstevel@tonic-gate     if (trans.length && (trans.data[trans.length-1] == '\0'))
3287c478bd9Sstevel@tonic-gate 	trans.length--;
3297c478bd9Sstevel@tonic-gate 
330*159d09a2SMark Phalan     Tprintf (("krb5_check_transited_list(trans=\"%.*s\", crealm=\"%.*s\", srealm=\"%.*s\")\n",
331*159d09a2SMark Phalan 	      (int) trans.length, trans.data,
332*159d09a2SMark Phalan 	      (int) crealm->length, crealm->data,
333*159d09a2SMark Phalan 	      (int) srealm->length, srealm->data));
3347c478bd9Sstevel@tonic-gate     if (trans.length == 0)
3357c478bd9Sstevel@tonic-gate 	return 0;
3367c478bd9Sstevel@tonic-gate     r = krb5_walk_realm_tree (ctx, crealm, srealm, &cdata.tgs,
3377c478bd9Sstevel@tonic-gate 			      KRB5_REALM_BRANCH_CHAR);
3387c478bd9Sstevel@tonic-gate     if (r) {
339*159d09a2SMark Phalan 	Tprintf (("error %ld\n", (long) r));
3407c478bd9Sstevel@tonic-gate 	return r;
3417c478bd9Sstevel@tonic-gate     }
3427c478bd9Sstevel@tonic-gate #ifdef DEBUG /* avoid compiler warning about 'd' unused */
3437c478bd9Sstevel@tonic-gate     {
3447c478bd9Sstevel@tonic-gate 	int i;
345*159d09a2SMark Phalan 	Tprintf (("tgs list = {\n"));
3467c478bd9Sstevel@tonic-gate 	for (i = 0; cdata.tgs[i]; i++) {
3477c478bd9Sstevel@tonic-gate 	    char *name;
3487c478bd9Sstevel@tonic-gate 	    r = krb5_unparse_name (ctx, cdata.tgs[i], &name);
349*159d09a2SMark Phalan 	    Tprintf (("\t'%s'\n", name));
3507c478bd9Sstevel@tonic-gate 	    free (name);
3517c478bd9Sstevel@tonic-gate 	}
352*159d09a2SMark Phalan 	Tprintf (("}\n"));
3537c478bd9Sstevel@tonic-gate     }
3547c478bd9Sstevel@tonic-gate #endif
3557c478bd9Sstevel@tonic-gate     cdata.ctx = ctx;
3567c478bd9Sstevel@tonic-gate     r = foreach_realm (check_realm_in_list, &cdata, crealm, srealm, &trans);
3577c478bd9Sstevel@tonic-gate     krb5_free_realm_tree (ctx, cdata.tgs);
3587c478bd9Sstevel@tonic-gate     return r;
3597c478bd9Sstevel@tonic-gate }
360*159d09a2SMark Phalan 
361*159d09a2SMark Phalan #ifdef TEST
362*159d09a2SMark Phalan 
363*159d09a2SMark Phalan static krb5_error_code
364*159d09a2SMark Phalan print_a_realm (krb5_data *realm, void *data)
365*159d09a2SMark Phalan {
366*159d09a2SMark Phalan     printf ("%.*s\n", (int) realm->length, realm->data);
367*159d09a2SMark Phalan     return 0;
368*159d09a2SMark Phalan }
369*159d09a2SMark Phalan 
370*159d09a2SMark Phalan int main (int argc, char *argv[]) {
371*159d09a2SMark Phalan     const char *me;
372*159d09a2SMark Phalan     krb5_data crealm, srealm, transit;
373*159d09a2SMark Phalan     krb5_error_code r;
374*159d09a2SMark Phalan     int expand_only = 0;
375*159d09a2SMark Phalan 
376*159d09a2SMark Phalan     me = strrchr (argv[0], '/');
377*159d09a2SMark Phalan     me = me ? me+1 : argv[0];
378*159d09a2SMark Phalan 
379*159d09a2SMark Phalan     while (argc > 3 && argv[1][0] == '-') {
380*159d09a2SMark Phalan 	if (!strcmp ("-v", argv[1]))
381*159d09a2SMark Phalan 	    verbose++, argc--, argv++;
382*159d09a2SMark Phalan 	else if (!strcmp ("-x", argv[1]))
383*159d09a2SMark Phalan 	    expand_only++, argc--, argv++;
384*159d09a2SMark Phalan 	else
385*159d09a2SMark Phalan 	    goto usage;
386*159d09a2SMark Phalan     }
387*159d09a2SMark Phalan 
388*159d09a2SMark Phalan     if (argc != 4) {
389*159d09a2SMark Phalan     usage:
390*159d09a2SMark Phalan 	printf ("usage: %s [-v] [-x] clientRealm serverRealm transitEncoding\n",
391*159d09a2SMark Phalan 		me);
392*159d09a2SMark Phalan 	return 1;
393*159d09a2SMark Phalan     }
394*159d09a2SMark Phalan 
395*159d09a2SMark Phalan     crealm.data = argv[1];
396*159d09a2SMark Phalan     crealm.length = strlen(argv[1]);
397*159d09a2SMark Phalan     srealm.data = argv[2];
398*159d09a2SMark Phalan     srealm.length = strlen(argv[2]);
399*159d09a2SMark Phalan     transit.data = argv[3];
400*159d09a2SMark Phalan     transit.length = strlen(argv[3]);
401*159d09a2SMark Phalan 
402*159d09a2SMark Phalan     if (expand_only) {
403*159d09a2SMark Phalan 
404*159d09a2SMark Phalan 	printf ("client realm: %s\n", argv[1]);
405*159d09a2SMark Phalan 	printf ("server realm: %s\n", argv[2]);
406*159d09a2SMark Phalan 	printf ("transit enc.: %s\n", argv[3]);
407*159d09a2SMark Phalan 
408*159d09a2SMark Phalan 	if (argv[3][0] == 0) {
409*159d09a2SMark Phalan 	    printf ("no other realms transited\n");
410*159d09a2SMark Phalan 	    return 0;
411*159d09a2SMark Phalan 	}
412*159d09a2SMark Phalan 
413*159d09a2SMark Phalan 	r = foreach_realm (print_a_realm, NULL, &crealm, &srealm, &transit);
414*159d09a2SMark Phalan 	if (r)
415*159d09a2SMark Phalan 	    printf ("--> returned error %ld\n", (long) r);
416*159d09a2SMark Phalan 	return r != 0;
417*159d09a2SMark Phalan 
418*159d09a2SMark Phalan     } else {
419*159d09a2SMark Phalan 
420*159d09a2SMark Phalan 	/* Actually check the values against the supplied krb5.conf file.  */
421*159d09a2SMark Phalan 	krb5_context ctx;
422*159d09a2SMark Phalan 	r = krb5_init_context (&ctx);
423*159d09a2SMark Phalan 	if (r) {
424*159d09a2SMark Phalan 	    com_err (me, r, "initializing krb5 context");
425*159d09a2SMark Phalan 	    return 1;
426*159d09a2SMark Phalan 	}
427*159d09a2SMark Phalan 	r = krb5_check_transited_list (ctx, &transit, &crealm, &srealm);
428*159d09a2SMark Phalan 	if (r == KRB5KRB_AP_ERR_ILL_CR_TKT) {
429*159d09a2SMark Phalan 	    printf ("NO\n");
430*159d09a2SMark Phalan 	} else if (r == 0) {
431*159d09a2SMark Phalan 	    printf ("YES\n");
432*159d09a2SMark Phalan 	} else {
433*159d09a2SMark Phalan 	    printf ("kablooey!\n");
434*159d09a2SMark Phalan 	    com_err (me, r, "checking transited-realm list");
435*159d09a2SMark Phalan 	    return 1;
436*159d09a2SMark Phalan 	}
437*159d09a2SMark Phalan 	return 0;
438*159d09a2SMark Phalan     }
439*159d09a2SMark Phalan }
440*159d09a2SMark Phalan 
441*159d09a2SMark Phalan #endif /* TEST */
442