xref: /minix3/crypto/external/bsd/heimdal/dist/lib/krb5/keytab_any.c (revision ebfedea0ce5bbe81e252ddf32d732e40fb633fae)
1 /*	$NetBSD: keytab_any.c,v 1.1.1.1 2011/04/13 18:15:34 elric Exp $	*/
2 
3 /*
4  * Copyright (c) 2001-2002 Kungliga Tekniska Högskolan
5  * (Royal Institute of Technology, Stockholm, Sweden).
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the Institute nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #include "krb5_locl.h"
37 
38 struct any_data {
39     krb5_keytab kt;
40     char *name;
41     struct any_data *next;
42 };
43 
44 static void
free_list(krb5_context context,struct any_data * a)45 free_list (krb5_context context, struct any_data *a)
46 {
47     struct any_data *next;
48 
49     for (; a != NULL; a = next) {
50 	next = a->next;
51 	free (a->name);
52 	if(a->kt)
53 	    krb5_kt_close(context, a->kt);
54 	free (a);
55     }
56 }
57 
58 static krb5_error_code KRB5_CALLCONV
any_resolve(krb5_context context,const char * name,krb5_keytab id)59 any_resolve(krb5_context context, const char *name, krb5_keytab id)
60 {
61     struct any_data *a, *a0 = NULL, *prev = NULL;
62     krb5_error_code ret;
63     char buf[256];
64 
65     while (strsep_copy(&name, ",", buf, sizeof(buf)) != -1) {
66 	a = calloc(1, sizeof(*a));
67 	if (a == NULL) {
68 	    ret = ENOMEM;
69 	    goto fail;
70 	}
71 	if (a0 == NULL) {
72 	    a0 = a;
73 	    a->name = strdup(buf);
74 	    if (a->name == NULL) {
75 		ret = ENOMEM;
76 		krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
77 		goto fail;
78 	    }
79 	} else
80 	    a->name = NULL;
81 	if (prev != NULL)
82 	    prev->next = a;
83 	a->next = NULL;
84 	ret = krb5_kt_resolve (context, buf, &a->kt);
85 	if (ret)
86 	    goto fail;
87 	prev = a;
88     }
89     if (a0 == NULL) {
90 	krb5_set_error_message(context, ENOENT, N_("empty ANY: keytab", ""));
91 	return ENOENT;
92     }
93     id->data = a0;
94     return 0;
95  fail:
96     free_list (context, a0);
97     return ret;
98 }
99 
100 static krb5_error_code KRB5_CALLCONV
any_get_name(krb5_context context,krb5_keytab id,char * name,size_t namesize)101 any_get_name (krb5_context context,
102 	      krb5_keytab id,
103 	      char *name,
104 	      size_t namesize)
105 {
106     struct any_data *a = id->data;
107     strlcpy(name, a->name, namesize);
108     return 0;
109 }
110 
111 static krb5_error_code KRB5_CALLCONV
any_close(krb5_context context,krb5_keytab id)112 any_close (krb5_context context,
113 	   krb5_keytab id)
114 {
115     struct any_data *a = id->data;
116 
117     free_list (context, a);
118     return 0;
119 }
120 
121 struct any_cursor_extra_data {
122     struct any_data *a;
123     krb5_kt_cursor cursor;
124 };
125 
126 static krb5_error_code KRB5_CALLCONV
any_start_seq_get(krb5_context context,krb5_keytab id,krb5_kt_cursor * c)127 any_start_seq_get(krb5_context context,
128 		  krb5_keytab id,
129 		  krb5_kt_cursor *c)
130 {
131     struct any_data *a = id->data;
132     struct any_cursor_extra_data *ed;
133     krb5_error_code ret;
134 
135     c->data = malloc (sizeof(struct any_cursor_extra_data));
136     if(c->data == NULL){
137 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
138 	return ENOMEM;
139     }
140     ed = (struct any_cursor_extra_data *)c->data;
141     for (ed->a = a; ed->a != NULL; ed->a = ed->a->next) {
142 	ret = krb5_kt_start_seq_get(context, ed->a->kt, &ed->cursor);
143 	if (ret == 0)
144 	    break;
145     }
146     if (ed->a == NULL) {
147 	free (c->data);
148 	c->data = NULL;
149 	krb5_clear_error_message (context);
150 	return KRB5_KT_END;
151     }
152     return 0;
153 }
154 
155 static krb5_error_code KRB5_CALLCONV
any_next_entry(krb5_context context,krb5_keytab id,krb5_keytab_entry * entry,krb5_kt_cursor * cursor)156 any_next_entry (krb5_context context,
157 		krb5_keytab id,
158 		krb5_keytab_entry *entry,
159 		krb5_kt_cursor *cursor)
160 {
161     krb5_error_code ret, ret2;
162     struct any_cursor_extra_data *ed;
163 
164     ed = (struct any_cursor_extra_data *)cursor->data;
165     do {
166 	ret = krb5_kt_next_entry(context, ed->a->kt, entry, &ed->cursor);
167 	if (ret == 0)
168 	    return 0;
169 	else if (ret != KRB5_KT_END)
170 	    return ret;
171 
172 	ret2 = krb5_kt_end_seq_get (context, ed->a->kt, &ed->cursor);
173 	if (ret2)
174 	    return ret2;
175 	while ((ed->a = ed->a->next) != NULL) {
176 	    ret2 = krb5_kt_start_seq_get(context, ed->a->kt, &ed->cursor);
177 	    if (ret2 == 0)
178 		break;
179 	}
180 	if (ed->a == NULL) {
181 	    krb5_clear_error_message (context);
182 	    return KRB5_KT_END;
183 	}
184     } while (1);
185 }
186 
187 static krb5_error_code KRB5_CALLCONV
any_end_seq_get(krb5_context context,krb5_keytab id,krb5_kt_cursor * cursor)188 any_end_seq_get(krb5_context context,
189 		krb5_keytab id,
190 		krb5_kt_cursor *cursor)
191 {
192     krb5_error_code ret = 0;
193     struct any_cursor_extra_data *ed;
194 
195     ed = (struct any_cursor_extra_data *)cursor->data;
196     if (ed->a != NULL)
197 	ret = krb5_kt_end_seq_get(context, ed->a->kt, &ed->cursor);
198     free (ed);
199     cursor->data = NULL;
200     return ret;
201 }
202 
203 static krb5_error_code KRB5_CALLCONV
any_add_entry(krb5_context context,krb5_keytab id,krb5_keytab_entry * entry)204 any_add_entry(krb5_context context,
205 	      krb5_keytab id,
206 	      krb5_keytab_entry *entry)
207 {
208     struct any_data *a = id->data;
209     krb5_error_code ret;
210     while(a != NULL) {
211 	ret = krb5_kt_add_entry(context, a->kt, entry);
212 	if(ret != 0 && ret != KRB5_KT_NOWRITE) {
213 	    krb5_set_error_message(context, ret,
214 				   N_("failed to add entry to %s", ""),
215 				   a->name);
216 	    return ret;
217 	}
218 	a = a->next;
219     }
220     return 0;
221 }
222 
223 static krb5_error_code KRB5_CALLCONV
any_remove_entry(krb5_context context,krb5_keytab id,krb5_keytab_entry * entry)224 any_remove_entry(krb5_context context,
225 		 krb5_keytab id,
226 		 krb5_keytab_entry *entry)
227 {
228     struct any_data *a = id->data;
229     krb5_error_code ret;
230     int found = 0;
231     while(a != NULL) {
232 	ret = krb5_kt_remove_entry(context, a->kt, entry);
233 	if(ret == 0)
234 	    found++;
235 	else {
236 	    if(ret != KRB5_KT_NOWRITE && ret != KRB5_KT_NOTFOUND) {
237 		krb5_set_error_message(context, ret,
238 				       N_("Failed to remove keytab "
239 					  "entry from %s", "keytab name"),
240 				       a->name);
241 		return ret;
242 	    }
243 	}
244 	a = a->next;
245     }
246     if(!found)
247 	return KRB5_KT_NOTFOUND;
248     return 0;
249 }
250 
251 const krb5_kt_ops krb5_any_ops = {
252     "ANY",
253     any_resolve,
254     any_get_name,
255     any_close,
256     NULL, /* destroy */
257     NULL, /* get */
258     any_start_seq_get,
259     any_next_entry,
260     any_end_seq_get,
261     any_add_entry,
262     any_remove_entry
263 };
264