etc/services - sync with NetBSD-8
[minix.git] / crypto / external / bsd / heimdal / dist / lib / krb5 / keytab_memory.c
blob3654d8159c5b33e960946fb2a00414a3156d52a0
1 /* $NetBSD: keytab_memory.c,v 1.1.1.1 2011/04/13 18:15:34 elric Exp $ */
3 /*
4 * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
36 #include "krb5_locl.h"
38 /* memory operations -------------------------------------------- */
40 struct mkt_data {
41 krb5_keytab_entry *entries;
42 int num_entries;
43 char *name;
44 int refcount;
45 struct mkt_data *next;
48 /* this mutex protects mkt_head, ->refcount, and ->next
49 * content is not protected (name is static and need no protection)
51 static HEIMDAL_MUTEX mkt_mutex = HEIMDAL_MUTEX_INITIALIZER;
52 static struct mkt_data *mkt_head;
55 static krb5_error_code KRB5_CALLCONV
56 mkt_resolve(krb5_context context, const char *name, krb5_keytab id)
58 struct mkt_data *d;
60 HEIMDAL_MUTEX_lock(&mkt_mutex);
62 for (d = mkt_head; d != NULL; d = d->next)
63 if (strcmp(d->name, name) == 0)
64 break;
65 if (d) {
66 if (d->refcount < 1)
67 krb5_abortx(context, "Double close on memory keytab, "
68 "refcount < 1 %d", d->refcount);
69 d->refcount++;
70 id->data = d;
71 HEIMDAL_MUTEX_unlock(&mkt_mutex);
72 return 0;
75 d = calloc(1, sizeof(*d));
76 if(d == NULL) {
77 HEIMDAL_MUTEX_unlock(&mkt_mutex);
78 krb5_set_error_message(context, ENOMEM,
79 N_("malloc: out of memory", ""));
80 return ENOMEM;
82 d->name = strdup(name);
83 if (d->name == NULL) {
84 HEIMDAL_MUTEX_unlock(&mkt_mutex);
85 free(d);
86 krb5_set_error_message(context, ENOMEM,
87 N_("malloc: out of memory", ""));
88 return ENOMEM;
90 d->entries = NULL;
91 d->num_entries = 0;
92 d->refcount = 1;
93 d->next = mkt_head;
94 mkt_head = d;
95 HEIMDAL_MUTEX_unlock(&mkt_mutex);
96 id->data = d;
97 return 0;
100 static krb5_error_code KRB5_CALLCONV
101 mkt_close(krb5_context context, krb5_keytab id)
103 struct mkt_data *d = id->data, **dp;
104 int i;
106 HEIMDAL_MUTEX_lock(&mkt_mutex);
107 if (d->refcount < 1)
108 krb5_abortx(context,
109 "krb5 internal error, memory keytab refcount < 1 on close");
111 if (--d->refcount > 0) {
112 HEIMDAL_MUTEX_unlock(&mkt_mutex);
113 return 0;
115 for (dp = &mkt_head; *dp != NULL; dp = &(*dp)->next) {
116 if (*dp == d) {
117 *dp = d->next;
118 break;
121 HEIMDAL_MUTEX_unlock(&mkt_mutex);
123 free(d->name);
124 for(i = 0; i < d->num_entries; i++)
125 krb5_kt_free_entry(context, &d->entries[i]);
126 free(d->entries);
127 free(d);
128 return 0;
131 static krb5_error_code KRB5_CALLCONV
132 mkt_get_name(krb5_context context,
133 krb5_keytab id,
134 char *name,
135 size_t namesize)
137 struct mkt_data *d = id->data;
138 strlcpy(name, d->name, namesize);
139 return 0;
142 static krb5_error_code KRB5_CALLCONV
143 mkt_start_seq_get(krb5_context context,
144 krb5_keytab id,
145 krb5_kt_cursor *c)
147 /* XXX */
148 c->fd = 0;
149 return 0;
152 static krb5_error_code KRB5_CALLCONV
153 mkt_next_entry(krb5_context context,
154 krb5_keytab id,
155 krb5_keytab_entry *entry,
156 krb5_kt_cursor *c)
158 struct mkt_data *d = id->data;
159 if(c->fd >= d->num_entries)
160 return KRB5_KT_END;
161 return krb5_kt_copy_entry_contents(context, &d->entries[c->fd++], entry);
164 static krb5_error_code KRB5_CALLCONV
165 mkt_end_seq_get(krb5_context context,
166 krb5_keytab id,
167 krb5_kt_cursor *cursor)
169 return 0;
172 static krb5_error_code KRB5_CALLCONV
173 mkt_add_entry(krb5_context context,
174 krb5_keytab id,
175 krb5_keytab_entry *entry)
177 struct mkt_data *d = id->data;
178 krb5_keytab_entry *tmp;
179 tmp = realloc(d->entries, (d->num_entries + 1) * sizeof(*d->entries));
180 if(tmp == NULL) {
181 krb5_set_error_message(context, ENOMEM,
182 N_("malloc: out of memory", ""));
183 return ENOMEM;
185 d->entries = tmp;
186 return krb5_kt_copy_entry_contents(context, entry,
187 &d->entries[d->num_entries++]);
190 static krb5_error_code KRB5_CALLCONV
191 mkt_remove_entry(krb5_context context,
192 krb5_keytab id,
193 krb5_keytab_entry *entry)
195 struct mkt_data *d = id->data;
196 krb5_keytab_entry *e, *end;
197 int found = 0;
199 if (d->num_entries == 0) {
200 krb5_clear_error_message(context);
201 return KRB5_KT_NOTFOUND;
204 /* do this backwards to minimize copying */
205 for(end = d->entries + d->num_entries, e = end - 1; e >= d->entries; e--) {
206 if(krb5_kt_compare(context, e, entry->principal,
207 entry->vno, entry->keyblock.keytype)) {
208 krb5_kt_free_entry(context, e);
209 memmove(e, e + 1, (end - e - 1) * sizeof(*e));
210 memset(end - 1, 0, sizeof(*end));
211 d->num_entries--;
212 end--;
213 found = 1;
216 if (!found) {
217 krb5_clear_error_message (context);
218 return KRB5_KT_NOTFOUND;
220 e = realloc(d->entries, d->num_entries * sizeof(*d->entries));
221 if(e != NULL || d->num_entries == 0)
222 d->entries = e;
223 return 0;
226 const krb5_kt_ops krb5_mkt_ops = {
227 "MEMORY",
228 mkt_resolve,
229 mkt_get_name,
230 mkt_close,
231 NULL, /* destroy */
232 NULL, /* get */
233 mkt_start_seq_get,
234 mkt_next_entry,
235 mkt_end_seq_get,
236 mkt_add_entry,
237 mkt_remove_entry