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 5811 : mkt_resolve(krb5_context context, const char *name, krb5_keytab id)
55 : {
56 2 : struct mkt_data *d;
57 :
58 2 : HEIMDAL_MUTEX_lock(&mkt_mutex);
59 :
60 6040 : for (d = mkt_head; d != NULL; d = d->next)
61 3829 : if (strcmp(d->name, name) == 0)
62 3600 : break;
63 5811 : if (d) {
64 3600 : if (d->refcount < 1)
65 0 : krb5_abortx(context, "Double close on memory keytab, "
66 : "refcount < 1 %d", d->refcount);
67 3600 : d->refcount++;
68 3600 : id->data = d;
69 0 : HEIMDAL_MUTEX_unlock(&mkt_mutex);
70 3600 : return 0;
71 : }
72 :
73 2211 : d = calloc(1, sizeof(*d));
74 2211 : if(d == NULL) {
75 0 : HEIMDAL_MUTEX_unlock(&mkt_mutex);
76 0 : return krb5_enomem(context);
77 : }
78 2211 : d->name = strdup(name);
79 2211 : if (d->name == NULL) {
80 0 : HEIMDAL_MUTEX_unlock(&mkt_mutex);
81 0 : free(d);
82 0 : return krb5_enomem(context);
83 : }
84 2211 : d->entries = NULL;
85 2211 : d->num_entries = 0;
86 2211 : d->refcount = 1;
87 2211 : d->next = mkt_head;
88 2211 : mkt_head = d;
89 2 : HEIMDAL_MUTEX_unlock(&mkt_mutex);
90 2211 : id->data = d;
91 2211 : return 0;
92 : }
93 :
94 : static krb5_error_code KRB5_CALLCONV
95 5777 : mkt_close(krb5_context context, krb5_keytab id)
96 : {
97 5777 : struct mkt_data *d = id->data, **dp;
98 0 : int i;
99 :
100 0 : HEIMDAL_MUTEX_lock(&mkt_mutex);
101 5777 : if (d->refcount < 1)
102 0 : krb5_abortx(context,
103 : "krb5 internal error, memory keytab refcount < 1 on close");
104 :
105 5777 : if (--d->refcount > 0) {
106 : HEIMDAL_MUTEX_unlock(&mkt_mutex);
107 3582 : return 0;
108 : }
109 2195 : for (dp = &mkt_head; *dp != NULL; dp = &(*dp)->next) {
110 2195 : if (*dp == d) {
111 2195 : *dp = d->next;
112 2195 : break;
113 : }
114 : }
115 0 : HEIMDAL_MUTEX_unlock(&mkt_mutex);
116 :
117 2195 : free(d->name);
118 18026 : for(i = 0; i < d->num_entries; i++)
119 15831 : krb5_kt_free_entry(context, &d->entries[i]);
120 2195 : free(d->entries);
121 2195 : free(d);
122 2195 : return 0;
123 : }
124 :
125 : static krb5_error_code KRB5_CALLCONV
126 4470 : mkt_get_name(krb5_context context,
127 : krb5_keytab id,
128 : char *name,
129 : size_t namesize)
130 : {
131 4470 : struct mkt_data *d = id->data;
132 4470 : strlcpy(name, d->name, namesize);
133 4470 : return 0;
134 : }
135 :
136 : static krb5_error_code KRB5_CALLCONV
137 4642 : mkt_start_seq_get(krb5_context context,
138 : krb5_keytab id,
139 : krb5_kt_cursor *c)
140 : {
141 : /* XXX */
142 4642 : c->fd = 0;
143 4642 : return 0;
144 : }
145 :
146 : static krb5_error_code KRB5_CALLCONV
147 10463 : mkt_next_entry(krb5_context context,
148 : krb5_keytab id,
149 : krb5_keytab_entry *entry,
150 : krb5_kt_cursor *c)
151 : {
152 10463 : struct mkt_data *d = id->data;
153 10463 : if(c->fd >= d->num_entries)
154 3305 : return KRB5_KT_END;
155 7154 : return krb5_kt_copy_entry_contents(context, &d->entries[c->fd++], entry);
156 : }
157 :
158 : static krb5_error_code KRB5_CALLCONV
159 4638 : mkt_end_seq_get(krb5_context context,
160 : krb5_keytab id,
161 : krb5_kt_cursor *cursor)
162 : {
163 4638 : return 0;
164 : }
165 :
166 : static krb5_error_code KRB5_CALLCONV
167 15951 : mkt_add_entry(krb5_context context,
168 : krb5_keytab id,
169 : krb5_keytab_entry *entry)
170 : {
171 15951 : struct mkt_data *d = id->data;
172 22 : krb5_keytab_entry *tmp;
173 15951 : tmp = realloc(d->entries, (d->num_entries + 1) * sizeof(*d->entries));
174 15951 : if (tmp == NULL)
175 0 : return krb5_enomem(context);
176 15951 : d->entries = tmp;
177 15951 : return krb5_kt_copy_entry_contents(context, entry,
178 15951 : &d->entries[d->num_entries++]);
179 : }
180 :
181 : static krb5_error_code KRB5_CALLCONV
182 16 : mkt_remove_entry(krb5_context context,
183 : krb5_keytab id,
184 : krb5_keytab_entry *entry)
185 : {
186 16 : struct mkt_data *d = id->data;
187 16 : krb5_keytab_entry *e, *end;
188 16 : int found = 0;
189 :
190 16 : if (d->num_entries == 0) {
191 0 : krb5_clear_error_message(context);
192 0 : return KRB5_KT_NOTFOUND;
193 : }
194 :
195 : /* do this backwards to minimize copying */
196 213 : for(end = d->entries + d->num_entries, e = end - 1; e >= d->entries; e--) {
197 197 : if(krb5_kt_compare(context, e, entry->principal,
198 197 : entry->vno, entry->keyblock.keytype)) {
199 16 : krb5_kt_free_entry(context, e);
200 16 : memmove(e, e + 1, (end - e - 1) * sizeof(*e));
201 16 : memset(end - 1, 0, sizeof(*end));
202 16 : d->num_entries--;
203 16 : end--;
204 16 : found = 1;
205 : }
206 : }
207 16 : if (!found) {
208 0 : krb5_clear_error_message (context);
209 0 : return KRB5_KT_NOTFOUND;
210 : }
211 16 : e = realloc(d->entries, d->num_entries * sizeof(*d->entries));
212 16 : if(e != NULL || d->num_entries == 0)
213 16 : d->entries = e;
214 0 : return 0;
215 : }
216 :
217 : const krb5_kt_ops krb5_mkt_ops = {
218 : "MEMORY",
219 : mkt_resolve,
220 : mkt_get_name,
221 : mkt_close,
222 : NULL, /* destroy */
223 : NULL, /* get */
224 : mkt_start_seq_get,
225 : mkt_next_entry,
226 : mkt_end_seq_get,
227 : mkt_add_entry,
228 : mkt_remove_entry,
229 : NULL,
230 : 0
231 : };
|