This commit was manufactured by cvs2svn to create tag
[heimdal.git] / lib / krb5 / mcache.c
blobaea0b5986519665e7fd83830ea9085c4c6c3ba85
1 /*
2 * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
34 #include "krb5_locl.h"
36 RCSID("$Id$");
38 typedef struct krb5_mcache {
39 char *name;
40 unsigned int refcnt;
41 int dead;
42 krb5_principal primary_principal;
43 struct link {
44 krb5_creds cred;
45 struct link *next;
46 } *creds;
47 struct krb5_mcache *next;
48 } krb5_mcache;
50 static struct krb5_mcache *mcc_head;
52 #define MCACHE(X) ((krb5_mcache *)(X)->data.data)
54 #define MISDEAD(X) ((X)->dead)
56 #define MCC_CURSOR(C) ((struct link*)(C))
58 static const char*
59 mcc_get_name(krb5_context context,
60 krb5_ccache id)
62 return MCACHE(id)->name;
65 static krb5_mcache *
66 mcc_alloc(const char *name)
68 krb5_mcache *m;
70 ALLOC(m, 1);
71 if(m == NULL)
72 return NULL;
73 if(name == NULL)
74 asprintf(&m->name, "%p", m);
75 else
76 m->name = strdup(name);
77 if(m->name == NULL) {
78 free(m);
79 return NULL;
81 m->dead = 0;
82 m->refcnt = 1;
83 m->primary_principal = NULL;
84 m->creds = NULL;
85 m->next = mcc_head;
86 mcc_head = m;
87 return m;
90 static krb5_error_code
91 mcc_resolve(krb5_context context, krb5_ccache *id, const char *res)
93 krb5_mcache *m;
95 for (m = mcc_head; m != NULL; m = m->next)
96 if (strcmp(m->name, res) == 0)
97 break;
99 if (m != NULL) {
100 m->refcnt++;
101 (*id)->data.data = m;
102 (*id)->data.length = sizeof(*m);
103 return 0;
106 m = mcc_alloc(res);
107 if (m == NULL) {
108 krb5_set_error_string (context, "malloc: out of memory");
109 return KRB5_CC_NOMEM;
112 (*id)->data.data = m;
113 (*id)->data.length = sizeof(*m);
115 return 0;
119 static krb5_error_code
120 mcc_gen_new(krb5_context context, krb5_ccache *id)
122 krb5_mcache *m;
124 m = mcc_alloc(NULL);
126 if (m == NULL) {
127 krb5_set_error_string (context, "malloc: out of memory");
128 return KRB5_CC_NOMEM;
131 (*id)->data.data = m;
132 (*id)->data.length = sizeof(*m);
134 return 0;
137 static krb5_error_code
138 mcc_initialize(krb5_context context,
139 krb5_ccache id,
140 krb5_principal primary_principal)
142 krb5_mcache *m = MCACHE(id);
143 m->dead = 0;
144 return krb5_copy_principal (context,
145 primary_principal,
146 &m->primary_principal);
149 static krb5_error_code
150 mcc_close(krb5_context context,
151 krb5_ccache id)
153 krb5_mcache *m = MCACHE(id);
155 if (--m->refcnt != 0)
156 return 0;
158 if (MISDEAD(m)) {
159 free (m->name);
160 krb5_data_free(&id->data);
163 return 0;
166 static krb5_error_code
167 mcc_destroy(krb5_context context,
168 krb5_ccache id)
170 krb5_mcache **n, *m = MCACHE(id);
171 struct link *l;
173 if (m->refcnt == 0)
174 krb5_abortx(context, "mcc_destroy: refcnt already 0");
176 if (!MISDEAD(m)) {
177 /* if this is an active mcache, remove it from the linked
178 list, and free all data */
179 for(n = &mcc_head; n && *n; n = &(*n)->next) {
180 if(m == *n) {
181 *n = m->next;
182 break;
185 if (m->primary_principal != NULL) {
186 krb5_free_principal (context, m->primary_principal);
187 m->primary_principal = NULL;
189 m->dead = 1;
191 l = m->creds;
192 while (l != NULL) {
193 struct link *old;
195 krb5_free_creds_contents (context, &l->cred);
196 old = l;
197 l = l->next;
198 free (old);
200 m->creds = NULL;
202 return 0;
205 static krb5_error_code
206 mcc_store_cred(krb5_context context,
207 krb5_ccache id,
208 krb5_creds *creds)
210 krb5_mcache *m = MCACHE(id);
211 krb5_error_code ret;
212 struct link *l;
214 if (MISDEAD(m))
215 return ENOENT;
217 l = malloc (sizeof(*l));
218 if (l == NULL) {
219 krb5_set_error_string (context, "malloc: out of memory");
220 return KRB5_CC_NOMEM;
222 l->next = m->creds;
223 m->creds = l;
224 memset (&l->cred, 0, sizeof(l->cred));
225 ret = krb5_copy_creds_contents (context, creds, &l->cred);
226 if (ret) {
227 m->creds = l->next;
228 free (l);
229 return ret;
231 return 0;
234 static krb5_error_code
235 mcc_get_principal(krb5_context context,
236 krb5_ccache id,
237 krb5_principal *principal)
239 krb5_mcache *m = MCACHE(id);
241 if (MISDEAD(m) || m->primary_principal == NULL)
242 return ENOENT;
243 return krb5_copy_principal (context,
244 m->primary_principal,
245 principal);
248 static krb5_error_code
249 mcc_get_first (krb5_context context,
250 krb5_ccache id,
251 krb5_cc_cursor *cursor)
253 krb5_mcache *m = MCACHE(id);
255 if (MISDEAD(m))
256 return ENOENT;
258 *cursor = m->creds;
259 return 0;
262 static krb5_error_code
263 mcc_get_next (krb5_context context,
264 krb5_ccache id,
265 krb5_cc_cursor *cursor,
266 krb5_creds *creds)
268 krb5_mcache *m = MCACHE(id);
269 struct link *l;
271 if (MISDEAD(m))
272 return ENOENT;
274 l = *cursor;
275 if (l != NULL) {
276 *cursor = l->next;
277 return krb5_copy_creds_contents (context,
278 &l->cred,
279 creds);
280 } else
281 return KRB5_CC_END;
284 static krb5_error_code
285 mcc_end_get (krb5_context context,
286 krb5_ccache id,
287 krb5_cc_cursor *cursor)
289 return 0;
292 static krb5_error_code
293 mcc_remove_cred(krb5_context context,
294 krb5_ccache id,
295 krb5_flags which,
296 krb5_creds *mcreds)
298 krb5_mcache *m = MCACHE(id);
299 struct link **q, *p;
300 for(q = &m->creds, p = *q; p; p = *q) {
301 if(krb5_compare_creds(context, which, mcreds, &p->cred)) {
302 *q = p->next;
303 krb5_free_creds_contents(context, &p->cred);
304 free(p);
305 } else
306 q = &p->next;
308 return 0;
311 static krb5_error_code
312 mcc_set_flags(krb5_context context,
313 krb5_ccache id,
314 krb5_flags flags)
316 return 0; /* XXX */
319 const krb5_cc_ops krb5_mcc_ops = {
320 "MEMORY",
321 mcc_get_name,
322 mcc_resolve,
323 mcc_gen_new,
324 mcc_initialize,
325 mcc_destroy,
326 mcc_close,
327 mcc_store_cred,
328 NULL, /* mcc_retrieve */
329 mcc_get_principal,
330 mcc_get_first,
331 mcc_get_next,
332 mcc_end_get,
333 mcc_remove_cred,
334 mcc_set_flags