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
process_intermediates(krb5_error_code (* fn)(krb5_data *,void *),void * data,const krb5_data * n1,const krb5_data * n2)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
maybe_join(krb5_data * last,krb5_data * buf,int bufsiz)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
foreach_realm(krb5_error_code (* fn)(krb5_data * comp,void * data),void * data,const krb5_data * crealm,const krb5_data * srealm,const krb5_data * transit)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
same_data(krb5_data * d1,krb5_data * d2)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
check_realm_in_list(krb5_data * realm,void * data)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
krb5_check_transited_list(krb5_context ctx,const krb5_data * trans_in,const krb5_data * crealm,const krb5_data * srealm)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
print_a_realm(krb5_data * realm,void * data)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
main(int argc,char * argv[])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