Line data Source code
1 : /*
2 : * Copyright (c) 1997 - 2001 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 : /* memory operations -------------------------------------------- */
37 :
38 : struct mkt_data {
39 : krb5_keytab_entry *entries;
40 : int num_entries;
41 : char *name;
42 : int refcount;
43 : struct mkt_data *next;
44 : };
45 :
46 : /* this mutex protects mkt_head, ->refcount, and ->next
47 : * content is not protected (name is static and need no protection)
48 : */
49 : static HEIMDAL_MUTEX mkt_mutex = HEIMDAL_MUTEX_INITIALIZER;
50 : static struct mkt_data *mkt_head;
51 :
52 :
53 : static krb5_error_code KRB5_CALLCONV
54 4025 : mkt_resolve(krb5_context context, const char *name, krb5_keytab id)
55 : {
56 : struct mkt_data *d;
57 :
58 : HEIMDAL_MUTEX_lock(&mkt_mutex);
59 :
60 4299 : for (d = mkt_head; d != NULL; d = d->next)
61 2784 : if (strcmp(d->name, name) == 0)
62 2510 : break;
63 4025 : if (d) {
64 2510 : if (d->refcount < 1)
65 0 : krb5_abortx(context, "Double close on memory keytab, "
66 : "refcount < 1 %d", d->refcount);
67 2510 : d->refcount++;
68 2510 : id->data = d;
69 : HEIMDAL_MUTEX_unlock(&mkt_mutex);
70 2510 : return 0;
71 : }
72 :
73 1515 : d = calloc(1, sizeof(*d));
74 1515 : if(d == NULL) {
75 : HEIMDAL_MUTEX_unlock(&mkt_mutex);
76 0 : krb5_set_error_message(context, ENOMEM,
77 0 : N_("malloc: out of memory", ""));
78 0 : return ENOMEM;
79 : }
80 1515 : d->name = strdup(name);
81 1515 : if (d->name == NULL) {
82 : HEIMDAL_MUTEX_unlock(&mkt_mutex);
83 0 : free(d);
84 0 : krb5_set_error_message(context, ENOMEM,
85 0 : N_("malloc: out of memory", ""));
86 0 : return ENOMEM;
87 : }
88 1515 : d->entries = NULL;
89 1515 : d->num_entries = 0;
90 1515 : d->refcount = 1;
91 1515 : d->next = mkt_head;
92 1515 : mkt_head = d;
93 : HEIMDAL_MUTEX_unlock(&mkt_mutex);
94 1515 : id->data = d;
95 1515 : return 0;
96 : }
97 :
98 : static krb5_error_code KRB5_CALLCONV
99 3983 : mkt_close(krb5_context context, krb5_keytab id)
100 : {
101 3983 : struct mkt_data *d = id->data, **dp;
102 : int i;
103 :
104 : HEIMDAL_MUTEX_lock(&mkt_mutex);
105 3983 : if (d->refcount < 1)
106 0 : krb5_abortx(context,
107 : "krb5 internal error, memory keytab refcount < 1 on close");
108 :
109 3983 : if (--d->refcount > 0) {
110 : HEIMDAL_MUTEX_unlock(&mkt_mutex);
111 2488 : return 0;
112 : }
113 1495 : for (dp = &mkt_head; *dp != NULL; dp = &(*dp)->next) {
114 1495 : if (*dp == d) {
115 1495 : *dp = d->next;
116 1495 : break;
117 : }
118 : }
119 : HEIMDAL_MUTEX_unlock(&mkt_mutex);
120 :
121 1495 : free(d->name);
122 10808 : for(i = 0; i < d->num_entries; i++)
123 9313 : krb5_kt_free_entry(context, &d->entries[i]);
124 1495 : free(d->entries);
125 1495 : free(d);
126 1495 : return 0;
127 : }
128 :
129 : static krb5_error_code KRB5_CALLCONV
130 3228 : mkt_get_name(krb5_context context,
131 : krb5_keytab id,
132 : char *name,
133 : size_t namesize)
134 : {
135 3228 : struct mkt_data *d = id->data;
136 3228 : strlcpy(name, d->name, namesize);
137 3228 : return 0;
138 : }
139 :
140 : static krb5_error_code KRB5_CALLCONV
141 3235 : mkt_start_seq_get(krb5_context context,
142 : krb5_keytab id,
143 : krb5_kt_cursor *c)
144 : {
145 : /* XXX */
146 3235 : c->fd = 0;
147 3235 : return 0;
148 : }
149 :
150 : static krb5_error_code KRB5_CALLCONV
151 7084 : mkt_next_entry(krb5_context context,
152 : krb5_keytab id,
153 : krb5_keytab_entry *entry,
154 : krb5_kt_cursor *c)
155 : {
156 7084 : struct mkt_data *d = id->data;
157 7084 : if(c->fd >= d->num_entries)
158 2227 : return KRB5_KT_END;
159 4853 : return krb5_kt_copy_entry_contents(context, &d->entries[c->fd++], entry);
160 : }
161 :
162 : static krb5_error_code KRB5_CALLCONV
163 1790 : mkt_end_seq_get(krb5_context context,
164 : krb5_keytab id,
165 : krb5_kt_cursor *cursor)
166 : {
167 1790 : return 0;
168 : }
169 :
170 : static krb5_error_code KRB5_CALLCONV
171 9461 : mkt_add_entry(krb5_context context,
172 : krb5_keytab id,
173 : krb5_keytab_entry *entry)
174 : {
175 9461 : struct mkt_data *d = id->data;
176 : krb5_keytab_entry *tmp;
177 9461 : tmp = realloc(d->entries, (d->num_entries + 1) * sizeof(*d->entries));
178 9461 : if(tmp == NULL) {
179 0 : krb5_set_error_message(context, ENOMEM,
180 0 : N_("malloc: out of memory", ""));
181 0 : return ENOMEM;
182 : }
183 9461 : d->entries = tmp;
184 9461 : return krb5_kt_copy_entry_contents(context, entry,
185 9461 : &d->entries[d->num_entries++]);
186 : }
187 :
188 : static krb5_error_code KRB5_CALLCONV
189 16 : mkt_remove_entry(krb5_context context,
190 : krb5_keytab id,
191 : krb5_keytab_entry *entry)
192 : {
193 16 : struct mkt_data *d = id->data;
194 : krb5_keytab_entry *e, *end;
195 16 : int found = 0;
196 :
197 16 : if (d->num_entries == 0) {
198 0 : krb5_clear_error_message(context);
199 0 : return KRB5_KT_NOTFOUND;
200 : }
201 :
202 : /* do this backwards to minimize copying */
203 213 : for(end = d->entries + d->num_entries, e = end - 1; e >= d->entries; e--) {
204 197 : if(krb5_kt_compare(context, e, entry->principal,
205 197 : entry->vno, entry->keyblock.keytype)) {
206 16 : krb5_kt_free_entry(context, e);
207 32 : memmove(e, e + 1, (end - e - 1) * sizeof(*e));
208 32 : memset(end - 1, 0, sizeof(*end));
209 16 : d->num_entries--;
210 16 : end--;
211 16 : found = 1;
212 : }
213 : }
214 16 : if (!found) {
215 0 : krb5_clear_error_message (context);
216 0 : return KRB5_KT_NOTFOUND;
217 : }
218 16 : e = realloc(d->entries, d->num_entries * sizeof(*d->entries));
219 16 : if(e != NULL || d->num_entries == 0)
220 16 : d->entries = e;
221 0 : return 0;
222 : }
223 :
224 : const krb5_kt_ops krb5_mkt_ops = {
225 : "MEMORY",
226 : mkt_resolve,
227 : mkt_get_name,
228 : mkt_close,
229 : NULL, /* destroy */
230 : NULL, /* get */
231 : mkt_start_seq_get,
232 : mkt_next_entry,
233 : mkt_end_seq_get,
234 : mkt_add_entry,
235 : mkt_remove_entry
236 : };
|