xref: /freebsd/crypto/heimdal/lib/krb5/keytab_any.c (revision 6a068746777241722b2b32c5d0bc443a2a64d80b)
1adb0ddaeSAssar Westerlund /*
2*ae771770SStanislav Sedov  * Copyright (c) 2001-2002 Kungliga Tekniska Högskolan
3adb0ddaeSAssar Westerlund  * (Royal Institute of Technology, Stockholm, Sweden).
4adb0ddaeSAssar Westerlund  * All rights reserved.
5adb0ddaeSAssar Westerlund  *
6adb0ddaeSAssar Westerlund  * Redistribution and use in source and binary forms, with or without
7adb0ddaeSAssar Westerlund  * modification, are permitted provided that the following conditions
8adb0ddaeSAssar Westerlund  * are met:
9adb0ddaeSAssar Westerlund  *
10adb0ddaeSAssar Westerlund  * 1. Redistributions of source code must retain the above copyright
11adb0ddaeSAssar Westerlund  *    notice, this list of conditions and the following disclaimer.
12adb0ddaeSAssar Westerlund  *
13adb0ddaeSAssar Westerlund  * 2. Redistributions in binary form must reproduce the above copyright
14adb0ddaeSAssar Westerlund  *    notice, this list of conditions and the following disclaimer in the
15adb0ddaeSAssar Westerlund  *    documentation and/or other materials provided with the distribution.
16adb0ddaeSAssar Westerlund  *
17adb0ddaeSAssar Westerlund  * 3. Neither the name of the Institute nor the names of its contributors
18adb0ddaeSAssar Westerlund  *    may be used to endorse or promote products derived from this software
19adb0ddaeSAssar Westerlund  *    without specific prior written permission.
20adb0ddaeSAssar Westerlund  *
21adb0ddaeSAssar Westerlund  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22adb0ddaeSAssar Westerlund  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23adb0ddaeSAssar Westerlund  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24adb0ddaeSAssar Westerlund  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25adb0ddaeSAssar Westerlund  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26adb0ddaeSAssar Westerlund  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27adb0ddaeSAssar Westerlund  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28adb0ddaeSAssar Westerlund  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29adb0ddaeSAssar Westerlund  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30adb0ddaeSAssar Westerlund  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31adb0ddaeSAssar Westerlund  * SUCH DAMAGE.
32adb0ddaeSAssar Westerlund  */
33adb0ddaeSAssar Westerlund 
34adb0ddaeSAssar Westerlund #include "krb5_locl.h"
35adb0ddaeSAssar Westerlund 
36adb0ddaeSAssar Westerlund struct any_data {
37adb0ddaeSAssar Westerlund     krb5_keytab kt;
38adb0ddaeSAssar Westerlund     char *name;
39adb0ddaeSAssar Westerlund     struct any_data *next;
40adb0ddaeSAssar Westerlund };
41adb0ddaeSAssar Westerlund 
42adb0ddaeSAssar Westerlund static void
free_list(krb5_context context,struct any_data * a)435bda878eSJacques Vidrine free_list (krb5_context context, struct any_data *a)
44adb0ddaeSAssar Westerlund {
45adb0ddaeSAssar Westerlund     struct any_data *next;
46adb0ddaeSAssar Westerlund 
47adb0ddaeSAssar Westerlund     for (; a != NULL; a = next) {
48adb0ddaeSAssar Westerlund 	next = a->next;
49adb0ddaeSAssar Westerlund 	free (a->name);
505bda878eSJacques Vidrine 	if(a->kt)
515bda878eSJacques Vidrine 	    krb5_kt_close(context, a->kt);
52adb0ddaeSAssar Westerlund 	free (a);
53adb0ddaeSAssar Westerlund     }
54adb0ddaeSAssar Westerlund }
55adb0ddaeSAssar Westerlund 
56*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
any_resolve(krb5_context context,const char * name,krb5_keytab id)57adb0ddaeSAssar Westerlund any_resolve(krb5_context context, const char *name, krb5_keytab id)
58adb0ddaeSAssar Westerlund {
59adb0ddaeSAssar Westerlund     struct any_data *a, *a0 = NULL, *prev = NULL;
60adb0ddaeSAssar Westerlund     krb5_error_code ret;
61adb0ddaeSAssar Westerlund     char buf[256];
62adb0ddaeSAssar Westerlund 
63adb0ddaeSAssar Westerlund     while (strsep_copy(&name, ",", buf, sizeof(buf)) != -1) {
64*ae771770SStanislav Sedov 	a = calloc(1, sizeof(*a));
65adb0ddaeSAssar Westerlund 	if (a == NULL) {
66adb0ddaeSAssar Westerlund 	    ret = ENOMEM;
67adb0ddaeSAssar Westerlund 	    goto fail;
68adb0ddaeSAssar Westerlund 	}
69adb0ddaeSAssar Westerlund 	if (a0 == NULL) {
70adb0ddaeSAssar Westerlund 	    a0 = a;
714137ff4cSJacques Vidrine 	    a->name = strdup(buf);
72adb0ddaeSAssar Westerlund 	    if (a->name == NULL) {
73adb0ddaeSAssar Westerlund 		ret = ENOMEM;
74*ae771770SStanislav Sedov 		krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
75adb0ddaeSAssar Westerlund 		goto fail;
76adb0ddaeSAssar Westerlund 	    }
77adb0ddaeSAssar Westerlund 	} else
78adb0ddaeSAssar Westerlund 	    a->name = NULL;
79adb0ddaeSAssar Westerlund 	if (prev != NULL)
80adb0ddaeSAssar Westerlund 	    prev->next = a;
81adb0ddaeSAssar Westerlund 	a->next = NULL;
82adb0ddaeSAssar Westerlund 	ret = krb5_kt_resolve (context, buf, &a->kt);
83adb0ddaeSAssar Westerlund 	if (ret)
84adb0ddaeSAssar Westerlund 	    goto fail;
85adb0ddaeSAssar Westerlund 	prev = a;
86adb0ddaeSAssar Westerlund     }
87adb0ddaeSAssar Westerlund     if (a0 == NULL) {
88*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOENT, N_("empty ANY: keytab", ""));
89adb0ddaeSAssar Westerlund 	return ENOENT;
90adb0ddaeSAssar Westerlund     }
91adb0ddaeSAssar Westerlund     id->data = a0;
92adb0ddaeSAssar Westerlund     return 0;
93adb0ddaeSAssar Westerlund  fail:
945bda878eSJacques Vidrine     free_list (context, a0);
95adb0ddaeSAssar Westerlund     return ret;
96adb0ddaeSAssar Westerlund }
97adb0ddaeSAssar Westerlund 
98*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
any_get_name(krb5_context context,krb5_keytab id,char * name,size_t namesize)99adb0ddaeSAssar Westerlund any_get_name (krb5_context context,
100adb0ddaeSAssar Westerlund 	      krb5_keytab id,
101adb0ddaeSAssar Westerlund 	      char *name,
102adb0ddaeSAssar Westerlund 	      size_t namesize)
103adb0ddaeSAssar Westerlund {
104adb0ddaeSAssar Westerlund     struct any_data *a = id->data;
105adb0ddaeSAssar Westerlund     strlcpy(name, a->name, namesize);
106adb0ddaeSAssar Westerlund     return 0;
107adb0ddaeSAssar Westerlund }
108adb0ddaeSAssar Westerlund 
109*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
any_close(krb5_context context,krb5_keytab id)110adb0ddaeSAssar Westerlund any_close (krb5_context context,
111adb0ddaeSAssar Westerlund 	   krb5_keytab id)
112adb0ddaeSAssar Westerlund {
113adb0ddaeSAssar Westerlund     struct any_data *a = id->data;
114adb0ddaeSAssar Westerlund 
1155bda878eSJacques Vidrine     free_list (context, a);
116adb0ddaeSAssar Westerlund     return 0;
117adb0ddaeSAssar Westerlund }
118adb0ddaeSAssar Westerlund 
119adb0ddaeSAssar Westerlund struct any_cursor_extra_data {
120adb0ddaeSAssar Westerlund     struct any_data *a;
121adb0ddaeSAssar Westerlund     krb5_kt_cursor cursor;
122adb0ddaeSAssar Westerlund };
123adb0ddaeSAssar Westerlund 
124*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
any_start_seq_get(krb5_context context,krb5_keytab id,krb5_kt_cursor * c)125adb0ddaeSAssar Westerlund any_start_seq_get(krb5_context context,
126adb0ddaeSAssar Westerlund 		  krb5_keytab id,
127adb0ddaeSAssar Westerlund 		  krb5_kt_cursor *c)
128adb0ddaeSAssar Westerlund {
129adb0ddaeSAssar Westerlund     struct any_data *a = id->data;
130adb0ddaeSAssar Westerlund     struct any_cursor_extra_data *ed;
131adb0ddaeSAssar Westerlund     krb5_error_code ret;
132adb0ddaeSAssar Westerlund 
133adb0ddaeSAssar Westerlund     c->data = malloc (sizeof(struct any_cursor_extra_data));
134adb0ddaeSAssar Westerlund     if(c->data == NULL){
135*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
136adb0ddaeSAssar Westerlund 	return ENOMEM;
137adb0ddaeSAssar Westerlund     }
138adb0ddaeSAssar Westerlund     ed = (struct any_cursor_extra_data *)c->data;
139*ae771770SStanislav Sedov     for (ed->a = a; ed->a != NULL; ed->a = ed->a->next) {
140adb0ddaeSAssar Westerlund 	ret = krb5_kt_start_seq_get(context, ed->a->kt, &ed->cursor);
141*ae771770SStanislav Sedov 	if (ret == 0)
142*ae771770SStanislav Sedov 	    break;
143*ae771770SStanislav Sedov     }
144*ae771770SStanislav Sedov     if (ed->a == NULL) {
145adb0ddaeSAssar Westerlund 	free (c->data);
146adb0ddaeSAssar Westerlund 	c->data = NULL;
147*ae771770SStanislav Sedov 	krb5_clear_error_message (context);
148*ae771770SStanislav Sedov 	return KRB5_KT_END;
149adb0ddaeSAssar Westerlund     }
150adb0ddaeSAssar Westerlund     return 0;
151adb0ddaeSAssar Westerlund }
152adb0ddaeSAssar Westerlund 
153*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
any_next_entry(krb5_context context,krb5_keytab id,krb5_keytab_entry * entry,krb5_kt_cursor * cursor)154adb0ddaeSAssar Westerlund any_next_entry (krb5_context context,
155adb0ddaeSAssar Westerlund 		krb5_keytab id,
156adb0ddaeSAssar Westerlund 		krb5_keytab_entry *entry,
157adb0ddaeSAssar Westerlund 		krb5_kt_cursor *cursor)
158adb0ddaeSAssar Westerlund {
159adb0ddaeSAssar Westerlund     krb5_error_code ret, ret2;
160adb0ddaeSAssar Westerlund     struct any_cursor_extra_data *ed;
161adb0ddaeSAssar Westerlund 
162adb0ddaeSAssar Westerlund     ed = (struct any_cursor_extra_data *)cursor->data;
163adb0ddaeSAssar Westerlund     do {
164adb0ddaeSAssar Westerlund 	ret = krb5_kt_next_entry(context, ed->a->kt, entry, &ed->cursor);
165adb0ddaeSAssar Westerlund 	if (ret == 0)
166adb0ddaeSAssar Westerlund 	    return 0;
167c19800e8SDoug Rabson 	else if (ret != KRB5_KT_END)
168c19800e8SDoug Rabson 	    return ret;
169c19800e8SDoug Rabson 
170adb0ddaeSAssar Westerlund 	ret2 = krb5_kt_end_seq_get (context, ed->a->kt, &ed->cursor);
171adb0ddaeSAssar Westerlund 	if (ret2)
172adb0ddaeSAssar Westerlund 	    return ret2;
1734137ff4cSJacques Vidrine 	while ((ed->a = ed->a->next) != NULL) {
1744137ff4cSJacques Vidrine 	    ret2 = krb5_kt_start_seq_get(context, ed->a->kt, &ed->cursor);
1754137ff4cSJacques Vidrine 	    if (ret2 == 0)
1764137ff4cSJacques Vidrine 		break;
1774137ff4cSJacques Vidrine 	}
178adb0ddaeSAssar Westerlund 	if (ed->a == NULL) {
179*ae771770SStanislav Sedov 	    krb5_clear_error_message (context);
1808373020dSJacques Vidrine 	    return KRB5_KT_END;
181adb0ddaeSAssar Westerlund 	}
182c19800e8SDoug Rabson     } while (1);
183adb0ddaeSAssar Westerlund }
184adb0ddaeSAssar Westerlund 
185*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
any_end_seq_get(krb5_context context,krb5_keytab id,krb5_kt_cursor * cursor)186adb0ddaeSAssar Westerlund any_end_seq_get(krb5_context context,
187adb0ddaeSAssar Westerlund 		krb5_keytab id,
188adb0ddaeSAssar Westerlund 		krb5_kt_cursor *cursor)
189adb0ddaeSAssar Westerlund {
190adb0ddaeSAssar Westerlund     krb5_error_code ret = 0;
191adb0ddaeSAssar Westerlund     struct any_cursor_extra_data *ed;
192adb0ddaeSAssar Westerlund 
193adb0ddaeSAssar Westerlund     ed = (struct any_cursor_extra_data *)cursor->data;
194adb0ddaeSAssar Westerlund     if (ed->a != NULL)
195adb0ddaeSAssar Westerlund 	ret = krb5_kt_end_seq_get(context, ed->a->kt, &ed->cursor);
196adb0ddaeSAssar Westerlund     free (ed);
197adb0ddaeSAssar Westerlund     cursor->data = NULL;
198adb0ddaeSAssar Westerlund     return ret;
199adb0ddaeSAssar Westerlund }
200adb0ddaeSAssar Westerlund 
201*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
any_add_entry(krb5_context context,krb5_keytab id,krb5_keytab_entry * entry)2024137ff4cSJacques Vidrine any_add_entry(krb5_context context,
2034137ff4cSJacques Vidrine 	      krb5_keytab id,
2044137ff4cSJacques Vidrine 	      krb5_keytab_entry *entry)
2054137ff4cSJacques Vidrine {
2064137ff4cSJacques Vidrine     struct any_data *a = id->data;
2074137ff4cSJacques Vidrine     krb5_error_code ret;
2084137ff4cSJacques Vidrine     while(a != NULL) {
2094137ff4cSJacques Vidrine 	ret = krb5_kt_add_entry(context, a->kt, entry);
2104137ff4cSJacques Vidrine 	if(ret != 0 && ret != KRB5_KT_NOWRITE) {
211*ae771770SStanislav Sedov 	    krb5_set_error_message(context, ret,
212*ae771770SStanislav Sedov 				   N_("failed to add entry to %s", ""),
2134137ff4cSJacques Vidrine 				   a->name);
2144137ff4cSJacques Vidrine 	    return ret;
2154137ff4cSJacques Vidrine 	}
2164137ff4cSJacques Vidrine 	a = a->next;
2174137ff4cSJacques Vidrine     }
2184137ff4cSJacques Vidrine     return 0;
2194137ff4cSJacques Vidrine }
2204137ff4cSJacques Vidrine 
221*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
any_remove_entry(krb5_context context,krb5_keytab id,krb5_keytab_entry * entry)2224137ff4cSJacques Vidrine any_remove_entry(krb5_context context,
2234137ff4cSJacques Vidrine 		 krb5_keytab id,
2244137ff4cSJacques Vidrine 		 krb5_keytab_entry *entry)
2254137ff4cSJacques Vidrine {
2264137ff4cSJacques Vidrine     struct any_data *a = id->data;
2274137ff4cSJacques Vidrine     krb5_error_code ret;
2284137ff4cSJacques Vidrine     int found = 0;
2294137ff4cSJacques Vidrine     while(a != NULL) {
2304137ff4cSJacques Vidrine 	ret = krb5_kt_remove_entry(context, a->kt, entry);
2314137ff4cSJacques Vidrine 	if(ret == 0)
2324137ff4cSJacques Vidrine 	    found++;
2334137ff4cSJacques Vidrine 	else {
2344137ff4cSJacques Vidrine 	    if(ret != KRB5_KT_NOWRITE && ret != KRB5_KT_NOTFOUND) {
235*ae771770SStanislav Sedov 		krb5_set_error_message(context, ret,
236*ae771770SStanislav Sedov 				       N_("Failed to remove keytab "
237*ae771770SStanislav Sedov 					  "entry from %s", "keytab name"),
2384137ff4cSJacques Vidrine 				       a->name);
2394137ff4cSJacques Vidrine 		return ret;
2404137ff4cSJacques Vidrine 	    }
2414137ff4cSJacques Vidrine 	}
2424137ff4cSJacques Vidrine 	a = a->next;
2434137ff4cSJacques Vidrine     }
2444137ff4cSJacques Vidrine     if(!found)
2454137ff4cSJacques Vidrine 	return KRB5_KT_NOTFOUND;
2464137ff4cSJacques Vidrine     return 0;
2474137ff4cSJacques Vidrine }
2484137ff4cSJacques Vidrine 
249adb0ddaeSAssar Westerlund const krb5_kt_ops krb5_any_ops = {
250adb0ddaeSAssar Westerlund     "ANY",
251adb0ddaeSAssar Westerlund     any_resolve,
252adb0ddaeSAssar Westerlund     any_get_name,
253adb0ddaeSAssar Westerlund     any_close,
254*ae771770SStanislav Sedov     NULL, /* destroy */
255adb0ddaeSAssar Westerlund     NULL, /* get */
256adb0ddaeSAssar Westerlund     any_start_seq_get,
257adb0ddaeSAssar Westerlund     any_next_entry,
258adb0ddaeSAssar Westerlund     any_end_seq_get,
2594137ff4cSJacques Vidrine     any_add_entry,
2604137ff4cSJacques Vidrine     any_remove_entry
261adb0ddaeSAssar Westerlund };
262