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