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