xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/krb5/keytab_any.c (revision d3273b5b76f5afaafe308cead5511dbb8df8c5e9)
1 /*	$NetBSD: keytab_any.c,v 1.2 2017/01/28 21:31:49 christos 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 = krb5_enomem(context);
69 	    goto fail;
70 	}
71 	if (a0 == NULL) {
72 	    a0 = a;
73 	    a->name = strdup(buf);
74 	    if (a->name == NULL) {
75 		ret = krb5_enomem(context);
76 		goto fail;
77 	    }
78 	} else
79 	    a->name = NULL;
80 	if (prev != NULL)
81 	    prev->next = a;
82 	a->next = NULL;
83 	ret = krb5_kt_resolve (context, buf, &a->kt);
84 	if (ret)
85 	    goto fail;
86 	prev = a;
87     }
88     if (a0 == NULL) {
89 	krb5_set_error_message(context, ENOENT, N_("empty ANY: keytab", ""));
90 	return ENOENT;
91     }
92     id->data = a0;
93     return 0;
94  fail:
95     free_list (context, a0);
96     return ret;
97 }
98 
99 static krb5_error_code KRB5_CALLCONV
any_get_name(krb5_context context,krb5_keytab id,char * name,size_t namesize)100 any_get_name (krb5_context context,
101 	      krb5_keytab id,
102 	      char *name,
103 	      size_t namesize)
104 {
105     struct any_data *a = id->data;
106     strlcpy(name, a->name, namesize);
107     return 0;
108 }
109 
110 static krb5_error_code KRB5_CALLCONV
any_close(krb5_context context,krb5_keytab id)111 any_close (krb5_context context,
112 	   krb5_keytab id)
113 {
114     struct any_data *a = id->data;
115 
116     free_list (context, a);
117     return 0;
118 }
119 
120 struct any_cursor_extra_data {
121     struct any_data *a;
122     krb5_kt_cursor cursor;
123 };
124 
125 static krb5_error_code KRB5_CALLCONV
any_start_seq_get(krb5_context context,krb5_keytab id,krb5_kt_cursor * c)126 any_start_seq_get(krb5_context context,
127 		  krb5_keytab id,
128 		  krb5_kt_cursor *c)
129 {
130     struct any_data *a = id->data;
131     struct any_cursor_extra_data *ed;
132     krb5_error_code ret;
133 
134     c->data = malloc (sizeof(struct any_cursor_extra_data));
135     if(c->data == NULL)
136 	return krb5_enomem(context);
137     ed = (struct any_cursor_extra_data *)c->data;
138     for (ed->a = a; ed->a != NULL; ed->a = ed->a->next) {
139 	ret = krb5_kt_start_seq_get(context, ed->a->kt, &ed->cursor);
140 	if (ret == 0)
141 	    break;
142     }
143     if (ed->a == NULL) {
144 	free (c->data);
145 	c->data = NULL;
146 	krb5_clear_error_message (context);
147 	return KRB5_KT_END;
148     }
149     return 0;
150 }
151 
152 static krb5_error_code KRB5_CALLCONV
any_next_entry(krb5_context context,krb5_keytab id,krb5_keytab_entry * entry,krb5_kt_cursor * cursor)153 any_next_entry (krb5_context context,
154 		krb5_keytab id,
155 		krb5_keytab_entry *entry,
156 		krb5_kt_cursor *cursor)
157 {
158     krb5_error_code ret, ret2;
159     struct any_cursor_extra_data *ed;
160 
161     ed = (struct any_cursor_extra_data *)cursor->data;
162     do {
163 	ret = krb5_kt_next_entry(context, ed->a->kt, entry, &ed->cursor);
164 	if (ret == 0)
165 	    return 0;
166 	else if (ret != KRB5_KT_END)
167 	    return ret;
168 
169 	ret2 = krb5_kt_end_seq_get (context, ed->a->kt, &ed->cursor);
170 	if (ret2)
171 	    return ret2;
172 	while ((ed->a = ed->a->next) != NULL) {
173 	    ret2 = krb5_kt_start_seq_get(context, ed->a->kt, &ed->cursor);
174 	    if (ret2 == 0)
175 		break;
176 	}
177 	if (ed->a == NULL) {
178 	    krb5_clear_error_message (context);
179 	    return KRB5_KT_END;
180 	}
181     } while (1);
182 }
183 
184 static krb5_error_code KRB5_CALLCONV
any_end_seq_get(krb5_context context,krb5_keytab id,krb5_kt_cursor * cursor)185 any_end_seq_get(krb5_context context,
186 		krb5_keytab id,
187 		krb5_kt_cursor *cursor)
188 {
189     krb5_error_code ret = 0;
190     struct any_cursor_extra_data *ed;
191 
192     ed = (struct any_cursor_extra_data *)cursor->data;
193     if (ed->a != NULL)
194 	ret = krb5_kt_end_seq_get(context, ed->a->kt, &ed->cursor);
195     free (ed);
196     cursor->data = NULL;
197     return ret;
198 }
199 
200 static krb5_error_code KRB5_CALLCONV
any_add_entry(krb5_context context,krb5_keytab id,krb5_keytab_entry * entry)201 any_add_entry(krb5_context context,
202 	      krb5_keytab id,
203 	      krb5_keytab_entry *entry)
204 {
205     struct any_data *a = id->data;
206     krb5_error_code ret;
207     while(a != NULL) {
208 	ret = krb5_kt_add_entry(context, a->kt, entry);
209 	if(ret != 0 && ret != KRB5_KT_NOWRITE) {
210 	    krb5_set_error_message(context, ret,
211 				   N_("failed to add entry to %s", ""),
212 				   a->name);
213 	    return ret;
214 	}
215 	a = a->next;
216     }
217     return 0;
218 }
219 
220 static krb5_error_code KRB5_CALLCONV
any_remove_entry(krb5_context context,krb5_keytab id,krb5_keytab_entry * entry)221 any_remove_entry(krb5_context context,
222 		 krb5_keytab id,
223 		 krb5_keytab_entry *entry)
224 {
225     struct any_data *a = id->data;
226     krb5_error_code ret;
227     int found = 0;
228     while(a != NULL) {
229 	ret = krb5_kt_remove_entry(context, a->kt, entry);
230 	if(ret == 0)
231 	    found++;
232 	else {
233 	    if(ret != KRB5_KT_NOWRITE && ret != KRB5_KT_NOTFOUND) {
234 		krb5_set_error_message(context, ret,
235 				       N_("Failed to remove keytab "
236 					  "entry from %s", "keytab name"),
237 				       a->name);
238 		return ret;
239 	    }
240 	}
241 	a = a->next;
242     }
243     if(!found)
244 	return KRB5_KT_NOTFOUND;
245     return 0;
246 }
247 
248 const krb5_kt_ops krb5_any_ops = {
249     "ANY",
250     any_resolve,
251     any_get_name,
252     any_close,
253     NULL, /* destroy */
254     NULL, /* get */
255     any_start_seq_get,
256     any_next_entry,
257     any_end_seq_get,
258     any_add_entry,
259     any_remove_entry,
260     NULL,
261     0
262 };
263