xref: /minix3/crypto/external/bsd/heimdal/dist/lib/krb5/transited.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: transited.c,v 1.1.1.2 2014/04/24 12:45:51 pettai Exp $	*/
2ebfedea0SLionel Sambuc 
3ebfedea0SLionel Sambuc /*
4ebfedea0SLionel Sambuc  * Copyright (c) 1997 - 2001, 2003 Kungliga Tekniska Högskolan
5ebfedea0SLionel Sambuc  * (Royal Institute of Technology, Stockholm, Sweden).
6ebfedea0SLionel Sambuc  * All rights reserved.
7ebfedea0SLionel Sambuc  *
8ebfedea0SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
9ebfedea0SLionel Sambuc  * modification, are permitted provided that the following conditions
10ebfedea0SLionel Sambuc  * are met:
11ebfedea0SLionel Sambuc  *
12ebfedea0SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
13ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
14ebfedea0SLionel Sambuc  *
15ebfedea0SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
16ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
17ebfedea0SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
18ebfedea0SLionel Sambuc  *
19ebfedea0SLionel Sambuc  * 3. Neither the name of the Institute nor the names of its contributors
20ebfedea0SLionel Sambuc  *    may be used to endorse or promote products derived from this software
21ebfedea0SLionel Sambuc  *    without specific prior written permission.
22ebfedea0SLionel Sambuc  *
23ebfedea0SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24ebfedea0SLionel Sambuc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25ebfedea0SLionel Sambuc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ebfedea0SLionel Sambuc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27ebfedea0SLionel Sambuc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28ebfedea0SLionel Sambuc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29ebfedea0SLionel Sambuc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30ebfedea0SLionel Sambuc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31ebfedea0SLionel Sambuc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32ebfedea0SLionel Sambuc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33ebfedea0SLionel Sambuc  * SUCH DAMAGE.
34ebfedea0SLionel Sambuc  */
35ebfedea0SLionel Sambuc 
36ebfedea0SLionel Sambuc #include "krb5_locl.h"
37ebfedea0SLionel Sambuc 
38ebfedea0SLionel Sambuc /* this is an attempt at one of the most horrible `compression'
39ebfedea0SLionel Sambuc    schemes that has ever been invented; it's so amazingly brain-dead
40ebfedea0SLionel Sambuc    that words can not describe it, and all this just to save a few
41ebfedea0SLionel Sambuc    silly bytes */
42ebfedea0SLionel Sambuc 
43ebfedea0SLionel Sambuc struct tr_realm {
44ebfedea0SLionel Sambuc     char *realm;
45ebfedea0SLionel Sambuc     unsigned leading_space:1;
46ebfedea0SLionel Sambuc     unsigned leading_slash:1;
47ebfedea0SLionel Sambuc     unsigned trailing_dot:1;
48ebfedea0SLionel Sambuc     struct tr_realm *next;
49ebfedea0SLionel Sambuc };
50ebfedea0SLionel Sambuc 
51ebfedea0SLionel Sambuc static void
free_realms(struct tr_realm * r)52ebfedea0SLionel Sambuc free_realms(struct tr_realm *r)
53ebfedea0SLionel Sambuc {
54ebfedea0SLionel Sambuc     struct tr_realm *p;
55ebfedea0SLionel Sambuc     while(r){
56ebfedea0SLionel Sambuc 	p = r;
57ebfedea0SLionel Sambuc 	r = r->next;
58ebfedea0SLionel Sambuc 	free(p->realm);
59ebfedea0SLionel Sambuc 	free(p);
60ebfedea0SLionel Sambuc     }
61ebfedea0SLionel Sambuc }
62ebfedea0SLionel Sambuc 
63ebfedea0SLionel Sambuc static int
make_path(krb5_context context,struct tr_realm * r,const char * from,const char * to)64ebfedea0SLionel Sambuc make_path(krb5_context context, struct tr_realm *r,
65ebfedea0SLionel Sambuc 	  const char *from, const char *to)
66ebfedea0SLionel Sambuc {
67ebfedea0SLionel Sambuc     struct tr_realm *tmp;
68ebfedea0SLionel Sambuc     const char *p;
69ebfedea0SLionel Sambuc 
70ebfedea0SLionel Sambuc     if(strlen(from) < strlen(to)){
71ebfedea0SLionel Sambuc 	const char *str;
72ebfedea0SLionel Sambuc 	str = from;
73ebfedea0SLionel Sambuc 	from = to;
74ebfedea0SLionel Sambuc 	to = str;
75ebfedea0SLionel Sambuc     }
76ebfedea0SLionel Sambuc 
77ebfedea0SLionel Sambuc     if(strcmp(from + strlen(from) - strlen(to), to) == 0){
78ebfedea0SLionel Sambuc 	p = from;
79ebfedea0SLionel Sambuc 	while(1){
80ebfedea0SLionel Sambuc 	    p = strchr(p, '.');
81ebfedea0SLionel Sambuc 	    if(p == NULL) {
82ebfedea0SLionel Sambuc 		krb5_clear_error_message (context);
83ebfedea0SLionel Sambuc 		return KRB5KDC_ERR_POLICY;
84ebfedea0SLionel Sambuc 	    }
85ebfedea0SLionel Sambuc 	    p++;
86ebfedea0SLionel Sambuc 	    if(strcmp(p, to) == 0)
87ebfedea0SLionel Sambuc 		break;
88ebfedea0SLionel Sambuc 	    tmp = calloc(1, sizeof(*tmp));
89*0a6a1f1dSLionel Sambuc 	    if(tmp == NULL)
90*0a6a1f1dSLionel Sambuc 		return krb5_enomem(context);
91ebfedea0SLionel Sambuc 	    tmp->next = r->next;
92ebfedea0SLionel Sambuc 	    r->next = tmp;
93ebfedea0SLionel Sambuc 	    tmp->realm = strdup(p);
94ebfedea0SLionel Sambuc 	    if(tmp->realm == NULL){
95ebfedea0SLionel Sambuc 		r->next = tmp->next;
96ebfedea0SLionel Sambuc 		free(tmp);
97*0a6a1f1dSLionel Sambuc 		return krb5_enomem(context);
98ebfedea0SLionel Sambuc 	    }
99ebfedea0SLionel Sambuc 	}
100ebfedea0SLionel Sambuc     }else if(strncmp(from, to, strlen(to)) == 0){
101ebfedea0SLionel Sambuc 	p = from + strlen(from);
102ebfedea0SLionel Sambuc 	while(1){
103ebfedea0SLionel Sambuc 	    while(p >= from && *p != '/') p--;
104ebfedea0SLionel Sambuc 	    if(p == from)
105ebfedea0SLionel Sambuc 		return KRB5KDC_ERR_POLICY;
106ebfedea0SLionel Sambuc 
107ebfedea0SLionel Sambuc 	    if(strncmp(to, from, p - from) == 0)
108ebfedea0SLionel Sambuc 		break;
109ebfedea0SLionel Sambuc 	    tmp = calloc(1, sizeof(*tmp));
110*0a6a1f1dSLionel Sambuc 	    if(tmp == NULL)
111*0a6a1f1dSLionel Sambuc 		return krb5_enomem(context);
112ebfedea0SLionel Sambuc 	    tmp->next = r->next;
113ebfedea0SLionel Sambuc 	    r->next = tmp;
114ebfedea0SLionel Sambuc 	    tmp->realm = malloc(p - from + 1);
115ebfedea0SLionel Sambuc 	    if(tmp->realm == NULL){
116ebfedea0SLionel Sambuc 		r->next = tmp->next;
117ebfedea0SLionel Sambuc 		free(tmp);
118*0a6a1f1dSLionel Sambuc 		return krb5_enomem(context);
119ebfedea0SLionel Sambuc 	    }
120ebfedea0SLionel Sambuc 	    memcpy(tmp->realm, from, p - from);
121ebfedea0SLionel Sambuc 	    tmp->realm[p - from] = '\0';
122ebfedea0SLionel Sambuc 	    p--;
123ebfedea0SLionel Sambuc 	}
124ebfedea0SLionel Sambuc     } else {
125ebfedea0SLionel Sambuc 	krb5_clear_error_message (context);
126ebfedea0SLionel Sambuc 	return KRB5KDC_ERR_POLICY;
127ebfedea0SLionel Sambuc     }
128ebfedea0SLionel Sambuc 
129ebfedea0SLionel Sambuc     return 0;
130ebfedea0SLionel Sambuc }
131ebfedea0SLionel Sambuc 
132ebfedea0SLionel Sambuc static int
make_paths(krb5_context context,struct tr_realm * realms,const char * client_realm,const char * server_realm)133ebfedea0SLionel Sambuc make_paths(krb5_context context,
134ebfedea0SLionel Sambuc 	   struct tr_realm *realms, const char *client_realm,
135ebfedea0SLionel Sambuc 	   const char *server_realm)
136ebfedea0SLionel Sambuc {
137ebfedea0SLionel Sambuc     struct tr_realm *r;
138ebfedea0SLionel Sambuc     int ret;
139ebfedea0SLionel Sambuc     const char *prev_realm = client_realm;
140ebfedea0SLionel Sambuc     const char *next_realm = NULL;
141ebfedea0SLionel Sambuc     for(r = realms; r; r = r->next){
142ebfedea0SLionel Sambuc 	/* it *might* be that you can have more than one empty
143ebfedea0SLionel Sambuc 	   component in a row, at least that's how I interpret the
144ebfedea0SLionel Sambuc 	   "," exception in 1510 */
145ebfedea0SLionel Sambuc 	if(r->realm[0] == '\0'){
146ebfedea0SLionel Sambuc 	    while(r->next && r->next->realm[0] == '\0')
147ebfedea0SLionel Sambuc 		r = r->next;
148ebfedea0SLionel Sambuc 	    if(r->next)
149ebfedea0SLionel Sambuc 		next_realm = r->next->realm;
150ebfedea0SLionel Sambuc 	    else
151ebfedea0SLionel Sambuc 		next_realm = server_realm;
152ebfedea0SLionel Sambuc 	    ret = make_path(context, r, prev_realm, next_realm);
153ebfedea0SLionel Sambuc 	    if(ret){
154ebfedea0SLionel Sambuc 		free_realms(realms);
155ebfedea0SLionel Sambuc 		return ret;
156ebfedea0SLionel Sambuc 	    }
157ebfedea0SLionel Sambuc 	}
158ebfedea0SLionel Sambuc 	prev_realm = r->realm;
159ebfedea0SLionel Sambuc     }
160ebfedea0SLionel Sambuc     return 0;
161ebfedea0SLionel Sambuc }
162ebfedea0SLionel Sambuc 
163ebfedea0SLionel Sambuc static int
expand_realms(krb5_context context,struct tr_realm * realms,const char * client_realm)164ebfedea0SLionel Sambuc expand_realms(krb5_context context,
165ebfedea0SLionel Sambuc 	      struct tr_realm *realms, const char *client_realm)
166ebfedea0SLionel Sambuc {
167ebfedea0SLionel Sambuc     struct tr_realm *r;
168ebfedea0SLionel Sambuc     const char *prev_realm = NULL;
169ebfedea0SLionel Sambuc     for(r = realms; r; r = r->next){
170ebfedea0SLionel Sambuc 	if(r->trailing_dot){
171ebfedea0SLionel Sambuc 	    char *tmp;
172ebfedea0SLionel Sambuc 	    size_t len;
173ebfedea0SLionel Sambuc 
174ebfedea0SLionel Sambuc 	    if(prev_realm == NULL)
175ebfedea0SLionel Sambuc 		prev_realm = client_realm;
176ebfedea0SLionel Sambuc 
177ebfedea0SLionel Sambuc 	    len = strlen(r->realm) + strlen(prev_realm) + 1;
178ebfedea0SLionel Sambuc 
179ebfedea0SLionel Sambuc 	    tmp = realloc(r->realm, len);
180ebfedea0SLionel Sambuc 	    if(tmp == NULL){
181ebfedea0SLionel Sambuc 		free_realms(realms);
182*0a6a1f1dSLionel Sambuc 		return krb5_enomem(context);
183ebfedea0SLionel Sambuc 	    }
184ebfedea0SLionel Sambuc 	    r->realm = tmp;
185ebfedea0SLionel Sambuc 	    strlcat(r->realm, prev_realm, len);
186ebfedea0SLionel Sambuc 	}else if(r->leading_slash && !r->leading_space && prev_realm){
187ebfedea0SLionel Sambuc 	    /* yet another exception: if you use x500-names, the
188ebfedea0SLionel Sambuc                leading realm doesn't have to be "quoted" with a space */
189ebfedea0SLionel Sambuc 	    char *tmp;
190ebfedea0SLionel Sambuc 	    size_t len = strlen(r->realm) + strlen(prev_realm) + 1;
191ebfedea0SLionel Sambuc 
192ebfedea0SLionel Sambuc 	    tmp = malloc(len);
193ebfedea0SLionel Sambuc 	    if(tmp == NULL){
194ebfedea0SLionel Sambuc 		free_realms(realms);
195*0a6a1f1dSLionel Sambuc 		return krb5_enomem(context);
196ebfedea0SLionel Sambuc 	    }
197ebfedea0SLionel Sambuc 	    strlcpy(tmp, prev_realm, len);
198ebfedea0SLionel Sambuc 	    strlcat(tmp, r->realm, len);
199ebfedea0SLionel Sambuc 	    free(r->realm);
200ebfedea0SLionel Sambuc 	    r->realm = tmp;
201ebfedea0SLionel Sambuc 	}
202ebfedea0SLionel Sambuc 	prev_realm = r->realm;
203ebfedea0SLionel Sambuc     }
204ebfedea0SLionel Sambuc     return 0;
205ebfedea0SLionel Sambuc }
206ebfedea0SLionel Sambuc 
207ebfedea0SLionel Sambuc static struct tr_realm *
make_realm(char * realm)208ebfedea0SLionel Sambuc make_realm(char *realm)
209ebfedea0SLionel Sambuc {
210ebfedea0SLionel Sambuc     struct tr_realm *r;
211ebfedea0SLionel Sambuc     char *p, *q;
212ebfedea0SLionel Sambuc     int quote = 0;
213ebfedea0SLionel Sambuc     r = calloc(1, sizeof(*r));
214ebfedea0SLionel Sambuc     if(r == NULL){
215ebfedea0SLionel Sambuc 	free(realm);
216ebfedea0SLionel Sambuc 	return NULL;
217ebfedea0SLionel Sambuc     }
218ebfedea0SLionel Sambuc     r->realm = realm;
219ebfedea0SLionel Sambuc     for(p = q = r->realm; *p; p++){
220ebfedea0SLionel Sambuc 	if(p == r->realm && *p == ' '){
221ebfedea0SLionel Sambuc 	    r->leading_space = 1;
222ebfedea0SLionel Sambuc 	    continue;
223ebfedea0SLionel Sambuc 	}
224ebfedea0SLionel Sambuc 	if(q == r->realm && *p == '/')
225ebfedea0SLionel Sambuc 	    r->leading_slash = 1;
226ebfedea0SLionel Sambuc 	if(quote){
227ebfedea0SLionel Sambuc 	    *q++ = *p;
228ebfedea0SLionel Sambuc 	    quote = 0;
229ebfedea0SLionel Sambuc 	    continue;
230ebfedea0SLionel Sambuc 	}
231ebfedea0SLionel Sambuc 	if(*p == '\\'){
232ebfedea0SLionel Sambuc 	    quote = 1;
233ebfedea0SLionel Sambuc 	    continue;
234ebfedea0SLionel Sambuc 	}
235ebfedea0SLionel Sambuc 	if(p[0] == '.' && p[1] == '\0')
236ebfedea0SLionel Sambuc 	    r->trailing_dot = 1;
237ebfedea0SLionel Sambuc 	*q++ = *p;
238ebfedea0SLionel Sambuc     }
239ebfedea0SLionel Sambuc     *q = '\0';
240ebfedea0SLionel Sambuc     return r;
241ebfedea0SLionel Sambuc }
242ebfedea0SLionel Sambuc 
243ebfedea0SLionel Sambuc static struct tr_realm*
append_realm(struct tr_realm * head,struct tr_realm * r)244ebfedea0SLionel Sambuc append_realm(struct tr_realm *head, struct tr_realm *r)
245ebfedea0SLionel Sambuc {
246ebfedea0SLionel Sambuc     struct tr_realm *p;
247ebfedea0SLionel Sambuc     if(head == NULL){
248ebfedea0SLionel Sambuc 	r->next = NULL;
249ebfedea0SLionel Sambuc 	return r;
250ebfedea0SLionel Sambuc     }
251ebfedea0SLionel Sambuc     p = head;
252ebfedea0SLionel Sambuc     while(p->next) p = p->next;
253ebfedea0SLionel Sambuc     p->next = r;
254ebfedea0SLionel Sambuc     return head;
255ebfedea0SLionel Sambuc }
256ebfedea0SLionel Sambuc 
257ebfedea0SLionel Sambuc static int
decode_realms(krb5_context context,const char * tr,int length,struct tr_realm ** realms)258ebfedea0SLionel Sambuc decode_realms(krb5_context context,
259ebfedea0SLionel Sambuc 	      const char *tr, int length, struct tr_realm **realms)
260ebfedea0SLionel Sambuc {
261ebfedea0SLionel Sambuc     struct tr_realm *r = NULL;
262ebfedea0SLionel Sambuc 
263ebfedea0SLionel Sambuc     char *tmp;
264ebfedea0SLionel Sambuc     int quote = 0;
265ebfedea0SLionel Sambuc     const char *start = tr;
266ebfedea0SLionel Sambuc     int i;
267ebfedea0SLionel Sambuc 
268ebfedea0SLionel Sambuc     for(i = 0; i < length; i++){
269ebfedea0SLionel Sambuc 	if(quote){
270ebfedea0SLionel Sambuc 	    quote = 0;
271ebfedea0SLionel Sambuc 	    continue;
272ebfedea0SLionel Sambuc 	}
273ebfedea0SLionel Sambuc 	if(tr[i] == '\\'){
274ebfedea0SLionel Sambuc 	    quote = 1;
275ebfedea0SLionel Sambuc 	    continue;
276ebfedea0SLionel Sambuc 	}
277ebfedea0SLionel Sambuc 	if(tr[i] == ','){
278ebfedea0SLionel Sambuc 	    tmp = malloc(tr + i - start + 1);
279*0a6a1f1dSLionel Sambuc 	    if(tmp == NULL)
280*0a6a1f1dSLionel Sambuc 		return krb5_enomem(context);
281ebfedea0SLionel Sambuc 	    memcpy(tmp, start, tr + i - start);
282ebfedea0SLionel Sambuc 	    tmp[tr + i - start] = '\0';
283ebfedea0SLionel Sambuc 	    r = make_realm(tmp);
284ebfedea0SLionel Sambuc 	    if(r == NULL){
285ebfedea0SLionel Sambuc 		free_realms(*realms);
286*0a6a1f1dSLionel Sambuc 		return krb5_enomem(context);
287ebfedea0SLionel Sambuc 	    }
288ebfedea0SLionel Sambuc 	    *realms = append_realm(*realms, r);
289ebfedea0SLionel Sambuc 	    start = tr + i + 1;
290ebfedea0SLionel Sambuc 	}
291ebfedea0SLionel Sambuc     }
292ebfedea0SLionel Sambuc     tmp = malloc(tr + i - start + 1);
293ebfedea0SLionel Sambuc     if(tmp == NULL){
294ebfedea0SLionel Sambuc 	free(*realms);
295*0a6a1f1dSLionel Sambuc 	return krb5_enomem(context);
296ebfedea0SLionel Sambuc     }
297ebfedea0SLionel Sambuc     memcpy(tmp, start, tr + i - start);
298ebfedea0SLionel Sambuc     tmp[tr + i - start] = '\0';
299ebfedea0SLionel Sambuc     r = make_realm(tmp);
300ebfedea0SLionel Sambuc     if(r == NULL){
301ebfedea0SLionel Sambuc 	free_realms(*realms);
302*0a6a1f1dSLionel Sambuc 	return krb5_enomem(context);
303ebfedea0SLionel Sambuc     }
304ebfedea0SLionel Sambuc     *realms = append_realm(*realms, r);
305ebfedea0SLionel Sambuc 
306ebfedea0SLionel Sambuc     return 0;
307ebfedea0SLionel Sambuc }
308ebfedea0SLionel Sambuc 
309ebfedea0SLionel Sambuc 
310ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_domain_x500_decode(krb5_context context,krb5_data tr,char *** realms,unsigned int * num_realms,const char * client_realm,const char * server_realm)311ebfedea0SLionel Sambuc krb5_domain_x500_decode(krb5_context context,
312ebfedea0SLionel Sambuc 			krb5_data tr, char ***realms, unsigned int *num_realms,
313ebfedea0SLionel Sambuc 			const char *client_realm, const char *server_realm)
314ebfedea0SLionel Sambuc {
315ebfedea0SLionel Sambuc     struct tr_realm *r = NULL;
316ebfedea0SLionel Sambuc     struct tr_realm *p, **q;
317ebfedea0SLionel Sambuc     int ret;
318ebfedea0SLionel Sambuc 
319ebfedea0SLionel Sambuc     if(tr.length == 0) {
320ebfedea0SLionel Sambuc 	*realms = NULL;
321ebfedea0SLionel Sambuc 	*num_realms = 0;
322ebfedea0SLionel Sambuc 	return 0;
323ebfedea0SLionel Sambuc     }
324ebfedea0SLionel Sambuc 
325ebfedea0SLionel Sambuc     /* split string in components */
326ebfedea0SLionel Sambuc     ret = decode_realms(context, tr.data, tr.length, &r);
327ebfedea0SLionel Sambuc     if(ret)
328ebfedea0SLionel Sambuc 	return ret;
329ebfedea0SLionel Sambuc 
330ebfedea0SLionel Sambuc     /* apply prefix rule */
331ebfedea0SLionel Sambuc     ret = expand_realms(context, r, client_realm);
332ebfedea0SLionel Sambuc     if(ret)
333ebfedea0SLionel Sambuc 	return ret;
334ebfedea0SLionel Sambuc 
335ebfedea0SLionel Sambuc     ret = make_paths(context, r, client_realm, server_realm);
336ebfedea0SLionel Sambuc     if(ret)
337ebfedea0SLionel Sambuc 	return ret;
338ebfedea0SLionel Sambuc 
339ebfedea0SLionel Sambuc     /* remove empty components and count realms */
340ebfedea0SLionel Sambuc     *num_realms = 0;
341ebfedea0SLionel Sambuc     for(q = &r; *q; ){
342ebfedea0SLionel Sambuc 	if((*q)->realm[0] == '\0'){
343ebfedea0SLionel Sambuc 	    p = *q;
344ebfedea0SLionel Sambuc 	    *q = (*q)->next;
345ebfedea0SLionel Sambuc 	    free(p->realm);
346ebfedea0SLionel Sambuc 	    free(p);
347ebfedea0SLionel Sambuc 	}else{
348ebfedea0SLionel Sambuc 	    q = &(*q)->next;
349ebfedea0SLionel Sambuc 	    (*num_realms)++;
350ebfedea0SLionel Sambuc 	}
351ebfedea0SLionel Sambuc     }
352*0a6a1f1dSLionel Sambuc     if (*num_realms + 1 > UINT_MAX/sizeof(**realms))
353ebfedea0SLionel Sambuc 	return ERANGE;
354ebfedea0SLionel Sambuc 
355ebfedea0SLionel Sambuc     {
356ebfedea0SLionel Sambuc 	char **R;
357ebfedea0SLionel Sambuc 	R = malloc((*num_realms + 1) * sizeof(*R));
358ebfedea0SLionel Sambuc 	if (R == NULL)
359*0a6a1f1dSLionel Sambuc 	    return krb5_enomem(context);
360ebfedea0SLionel Sambuc 	*realms = R;
361ebfedea0SLionel Sambuc 	while(r){
362ebfedea0SLionel Sambuc 	    *R++ = r->realm;
363ebfedea0SLionel Sambuc 	    p = r->next;
364ebfedea0SLionel Sambuc 	    free(r);
365ebfedea0SLionel Sambuc 	    r = p;
366ebfedea0SLionel Sambuc 	}
367ebfedea0SLionel Sambuc     }
368ebfedea0SLionel Sambuc     return 0;
369ebfedea0SLionel Sambuc }
370ebfedea0SLionel Sambuc 
371ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_domain_x500_encode(char ** realms,unsigned int num_realms,krb5_data * encoding)372ebfedea0SLionel Sambuc krb5_domain_x500_encode(char **realms, unsigned int num_realms,
373ebfedea0SLionel Sambuc 			krb5_data *encoding)
374ebfedea0SLionel Sambuc {
375ebfedea0SLionel Sambuc     char *s = NULL;
376ebfedea0SLionel Sambuc     int len = 0;
377ebfedea0SLionel Sambuc     unsigned int i;
378ebfedea0SLionel Sambuc     krb5_data_zero(encoding);
379ebfedea0SLionel Sambuc     if (num_realms == 0)
380ebfedea0SLionel Sambuc 	return 0;
381ebfedea0SLionel Sambuc     for(i = 0; i < num_realms; i++){
382ebfedea0SLionel Sambuc 	len += strlen(realms[i]);
383ebfedea0SLionel Sambuc 	if(realms[i][0] == '/')
384ebfedea0SLionel Sambuc 	    len++;
385ebfedea0SLionel Sambuc     }
386ebfedea0SLionel Sambuc     len += num_realms - 1;
387ebfedea0SLionel Sambuc     s = malloc(len + 1);
388ebfedea0SLionel Sambuc     if (s == NULL)
389ebfedea0SLionel Sambuc 	return ENOMEM;
390ebfedea0SLionel Sambuc     *s = '\0';
391ebfedea0SLionel Sambuc     for(i = 0; i < num_realms; i++){
392*0a6a1f1dSLionel Sambuc 	if(i)
393ebfedea0SLionel Sambuc 	    strlcat(s, ",", len + 1);
394ebfedea0SLionel Sambuc 	if(realms[i][0] == '/')
395ebfedea0SLionel Sambuc 	    strlcat(s, " ", len + 1);
396ebfedea0SLionel Sambuc 	strlcat(s, realms[i], len + 1);
397ebfedea0SLionel Sambuc     }
398ebfedea0SLionel Sambuc     encoding->data = s;
399ebfedea0SLionel Sambuc     encoding->length = strlen(s);
400ebfedea0SLionel Sambuc     return 0;
401ebfedea0SLionel Sambuc }
402ebfedea0SLionel Sambuc 
403ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_check_transited(krb5_context context,krb5_const_realm client_realm,krb5_const_realm server_realm,krb5_realm * realms,unsigned int num_realms,int * bad_realm)404ebfedea0SLionel Sambuc krb5_check_transited(krb5_context context,
405ebfedea0SLionel Sambuc 		     krb5_const_realm client_realm,
406ebfedea0SLionel Sambuc 		     krb5_const_realm server_realm,
407ebfedea0SLionel Sambuc 		     krb5_realm *realms,
408ebfedea0SLionel Sambuc 		     unsigned int num_realms,
409ebfedea0SLionel Sambuc 		     int *bad_realm)
410ebfedea0SLionel Sambuc {
411ebfedea0SLionel Sambuc     char **tr_realms;
412ebfedea0SLionel Sambuc     char **p;
413*0a6a1f1dSLionel Sambuc     size_t i;
414ebfedea0SLionel Sambuc 
415ebfedea0SLionel Sambuc     if(num_realms == 0)
416ebfedea0SLionel Sambuc 	return 0;
417ebfedea0SLionel Sambuc 
418ebfedea0SLionel Sambuc     tr_realms = krb5_config_get_strings(context, NULL,
419ebfedea0SLionel Sambuc 					"capaths",
420ebfedea0SLionel Sambuc 					client_realm,
421ebfedea0SLionel Sambuc 					server_realm,
422ebfedea0SLionel Sambuc 					NULL);
423ebfedea0SLionel Sambuc     for(i = 0; i < num_realms; i++) {
424ebfedea0SLionel Sambuc 	for(p = tr_realms; p && *p; p++) {
425ebfedea0SLionel Sambuc 	    if(strcmp(*p, realms[i]) == 0)
426ebfedea0SLionel Sambuc 		break;
427ebfedea0SLionel Sambuc 	}
428ebfedea0SLionel Sambuc 	if(p == NULL || *p == NULL) {
429ebfedea0SLionel Sambuc 	    krb5_config_free_strings(tr_realms);
430ebfedea0SLionel Sambuc 	    krb5_set_error_message (context, KRB5KRB_AP_ERR_ILL_CR_TKT,
431ebfedea0SLionel Sambuc 				    N_("no transit allowed "
432ebfedea0SLionel Sambuc 				       "through realm %s", ""),
433ebfedea0SLionel Sambuc 				    realms[i]);
434ebfedea0SLionel Sambuc 	    if(bad_realm)
435ebfedea0SLionel Sambuc 		*bad_realm = i;
436ebfedea0SLionel Sambuc 	    return KRB5KRB_AP_ERR_ILL_CR_TKT;
437ebfedea0SLionel Sambuc 	}
438ebfedea0SLionel Sambuc     }
439ebfedea0SLionel Sambuc     krb5_config_free_strings(tr_realms);
440ebfedea0SLionel Sambuc     return 0;
441ebfedea0SLionel Sambuc }
442ebfedea0SLionel Sambuc 
443ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_check_transited_realms(krb5_context context,const char * const * realms,unsigned int num_realms,int * bad_realm)444ebfedea0SLionel Sambuc krb5_check_transited_realms(krb5_context context,
445ebfedea0SLionel Sambuc 			    const char *const *realms,
446ebfedea0SLionel Sambuc 			    unsigned int num_realms,
447ebfedea0SLionel Sambuc 			    int *bad_realm)
448ebfedea0SLionel Sambuc {
449*0a6a1f1dSLionel Sambuc     size_t i;
450ebfedea0SLionel Sambuc     int ret = 0;
451ebfedea0SLionel Sambuc     char **bad_realms = krb5_config_get_strings(context, NULL,
452ebfedea0SLionel Sambuc 						"libdefaults",
453ebfedea0SLionel Sambuc 						"transited_realms_reject",
454ebfedea0SLionel Sambuc 						NULL);
455ebfedea0SLionel Sambuc     if(bad_realms == NULL)
456ebfedea0SLionel Sambuc 	return 0;
457ebfedea0SLionel Sambuc 
458ebfedea0SLionel Sambuc     for(i = 0; i < num_realms; i++) {
459ebfedea0SLionel Sambuc 	char **p;
460ebfedea0SLionel Sambuc 	for(p = bad_realms; *p; p++)
461ebfedea0SLionel Sambuc 	    if(strcmp(*p, realms[i]) == 0) {
462ebfedea0SLionel Sambuc 		ret = KRB5KRB_AP_ERR_ILL_CR_TKT;
463ebfedea0SLionel Sambuc 		krb5_set_error_message (context, ret,
464ebfedea0SLionel Sambuc 					N_("no transit allowed "
465ebfedea0SLionel Sambuc 					   "through realm %s", ""),
466ebfedea0SLionel Sambuc 					*p);
467ebfedea0SLionel Sambuc 		if(bad_realm)
468ebfedea0SLionel Sambuc 		    *bad_realm = i;
469ebfedea0SLionel Sambuc 		break;
470ebfedea0SLionel Sambuc 	    }
471ebfedea0SLionel Sambuc     }
472ebfedea0SLionel Sambuc     krb5_config_free_strings(bad_realms);
473ebfedea0SLionel Sambuc     return ret;
474ebfedea0SLionel Sambuc }
475ebfedea0SLionel Sambuc 
476ebfedea0SLionel Sambuc #if 0
477ebfedea0SLionel Sambuc int
478ebfedea0SLionel Sambuc main(int argc, char **argv)
479ebfedea0SLionel Sambuc {
480ebfedea0SLionel Sambuc     krb5_data x;
481ebfedea0SLionel Sambuc     char **r;
482ebfedea0SLionel Sambuc     int num, i;
483ebfedea0SLionel Sambuc     x.data = argv[1];
484ebfedea0SLionel Sambuc     x.length = strlen(x.data);
485ebfedea0SLionel Sambuc     if(domain_expand(x, &r, &num, argv[2], argv[3]))
486ebfedea0SLionel Sambuc 	exit(1);
487ebfedea0SLionel Sambuc     for(i = 0; i < num; i++)
488ebfedea0SLionel Sambuc 	printf("%s\n", r[i]);
489ebfedea0SLionel Sambuc     return 0;
490ebfedea0SLionel Sambuc }
491ebfedea0SLionel Sambuc #endif
492ebfedea0SLionel Sambuc 
493