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