1b528cefcSMark Murray /*
21c43270aSJacques Vidrine * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan
3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray * All rights reserved.
5b528cefcSMark Murray *
6b528cefcSMark Murray * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
7b528cefcSMark Murray *
8b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without
9b528cefcSMark Murray * modification, are permitted provided that the following conditions
10b528cefcSMark Murray * are met:
11b528cefcSMark Murray *
12b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright
13b528cefcSMark Murray * notice, this list of conditions and the following disclaimer.
14b528cefcSMark Murray *
15b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright
16b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the
17b528cefcSMark Murray * documentation and/or other materials provided with the distribution.
18b528cefcSMark Murray *
19b528cefcSMark Murray * 3. Neither the name of the Institute nor the names of its contributors
20b528cefcSMark Murray * may be used to endorse or promote products derived from this software
21b528cefcSMark Murray * without specific prior written permission.
22b528cefcSMark Murray *
23b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33b528cefcSMark Murray * SUCH DAMAGE.
34b528cefcSMark Murray */
35b528cefcSMark Murray
36c19800e8SDoug Rabson #include "krb5_locl.h"
37b528cefcSMark Murray
38b528cefcSMark Murray typedef struct krb5_mcache {
395e9cd1aeSAssar Westerlund char *name;
405e9cd1aeSAssar Westerlund unsigned int refcnt;
411c43270aSJacques Vidrine int dead;
42b528cefcSMark Murray krb5_principal primary_principal;
43b528cefcSMark Murray struct link {
44b528cefcSMark Murray krb5_creds cred;
45b528cefcSMark Murray struct link *next;
46b528cefcSMark Murray } *creds;
475e9cd1aeSAssar Westerlund struct krb5_mcache *next;
48b528cefcSMark Murray time_t mtime;
49b528cefcSMark Murray krb5_deltat kdc_offset;
50c19800e8SDoug Rabson } krb5_mcache;
515e9cd1aeSAssar Westerlund
525e9cd1aeSAssar Westerlund static HEIMDAL_MUTEX mcc_mutex = HEIMDAL_MUTEX_INITIALIZER;
535e9cd1aeSAssar Westerlund static struct krb5_mcache *mcc_head;
545e9cd1aeSAssar Westerlund
551c43270aSJacques Vidrine #define MCACHE(X) ((krb5_mcache *)(X)->data.data)
565e9cd1aeSAssar Westerlund
578373020dSJacques Vidrine #define MISDEAD(X) ((X)->dead)
58b528cefcSMark Murray
59b528cefcSMark Murray static const char* KRB5_CALLCONV
mcc_get_name(krb5_context context,krb5_ccache id)60b528cefcSMark Murray mcc_get_name(krb5_context context,
615e9cd1aeSAssar Westerlund krb5_ccache id)
625e9cd1aeSAssar Westerlund {
635e9cd1aeSAssar Westerlund return MCACHE(id)->name;
645e9cd1aeSAssar Westerlund }
655e9cd1aeSAssar Westerlund
665e9cd1aeSAssar Westerlund static krb5_mcache * KRB5_CALLCONV
mcc_alloc(const char * name)67c19800e8SDoug Rabson mcc_alloc(const char *name)
68adb0ddaeSAssar Westerlund {
695e9cd1aeSAssar Westerlund krb5_mcache *m, *m_c;
705e9cd1aeSAssar Westerlund int ret = 0;
715e9cd1aeSAssar Westerlund
725e9cd1aeSAssar Westerlund ALLOC(m, 1);
735e9cd1aeSAssar Westerlund if(m == NULL)
745e9cd1aeSAssar Westerlund return NULL;
755e9cd1aeSAssar Westerlund if(name == NULL)
765e9cd1aeSAssar Westerlund ret = asprintf(&m->name, "%p", m);
775e9cd1aeSAssar Westerlund else
785e9cd1aeSAssar Westerlund m->name = strdup(name);
795e9cd1aeSAssar Westerlund if(ret < 0 || m->name == NULL) {
80c19800e8SDoug Rabson free(m);
81c19800e8SDoug Rabson return NULL;
82c19800e8SDoug Rabson }
83c19800e8SDoug Rabson /* check for dups first */
84c19800e8SDoug Rabson HEIMDAL_MUTEX_lock(&mcc_mutex);
85c19800e8SDoug Rabson for (m_c = mcc_head; m_c != NULL; m_c = m_c->next)
86c19800e8SDoug Rabson if (strcmp(m->name, m_c->name) == 0)
87c19800e8SDoug Rabson break;
88c19800e8SDoug Rabson if (m_c) {
89c19800e8SDoug Rabson free(m->name);
90c19800e8SDoug Rabson free(m);
91c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&mcc_mutex);
921c43270aSJacques Vidrine return NULL;
935e9cd1aeSAssar Westerlund }
945e9cd1aeSAssar Westerlund
955e9cd1aeSAssar Westerlund m->dead = 0;
965e9cd1aeSAssar Westerlund m->refcnt = 1;
975e9cd1aeSAssar Westerlund m->primary_principal = NULL;
98c19800e8SDoug Rabson m->creds = NULL;
995e9cd1aeSAssar Westerlund m->mtime = time(NULL);
100b528cefcSMark Murray m->kdc_offset = 0;
101b528cefcSMark Murray m->next = mcc_head;
102b528cefcSMark Murray mcc_head = m;
103b528cefcSMark Murray HEIMDAL_MUTEX_unlock(&mcc_mutex);
104b528cefcSMark Murray return m;
1055e9cd1aeSAssar Westerlund }
1065e9cd1aeSAssar Westerlund
107c19800e8SDoug Rabson static krb5_error_code KRB5_CALLCONV
mcc_resolve(krb5_context context,krb5_ccache * id,const char * res)1085e9cd1aeSAssar Westerlund mcc_resolve(krb5_context context, krb5_ccache *id, const char *res)
1095e9cd1aeSAssar Westerlund {
1105e9cd1aeSAssar Westerlund krb5_mcache *m;
111c19800e8SDoug Rabson
1125e9cd1aeSAssar Westerlund HEIMDAL_MUTEX_lock(&mcc_mutex);
1135e9cd1aeSAssar Westerlund for (m = mcc_head; m != NULL; m = m->next)
1145e9cd1aeSAssar Westerlund if (strcmp(m->name, res) == 0)
1155e9cd1aeSAssar Westerlund break;
1165e9cd1aeSAssar Westerlund HEIMDAL_MUTEX_unlock(&mcc_mutex);
1175e9cd1aeSAssar Westerlund
118b528cefcSMark Murray if (m != NULL) {
119b528cefcSMark Murray m->refcnt++;
1205e9cd1aeSAssar Westerlund (*id)->data.data = m;
121adb0ddaeSAssar Westerlund (*id)->data.length = sizeof(*m);
122adb0ddaeSAssar Westerlund return 0;
1235e9cd1aeSAssar Westerlund }
124adb0ddaeSAssar Westerlund
1255e9cd1aeSAssar Westerlund m = mcc_alloc(res);
1265e9cd1aeSAssar Westerlund if (m == NULL) {
1275e9cd1aeSAssar Westerlund krb5_set_error_message(context, KRB5_CC_NOMEM,
1285e9cd1aeSAssar Westerlund N_("malloc: out of memory", ""));
1295e9cd1aeSAssar Westerlund return KRB5_CC_NOMEM;
1305e9cd1aeSAssar Westerlund }
1315e9cd1aeSAssar Westerlund
1325e9cd1aeSAssar Westerlund (*id)->data.data = m;
133b528cefcSMark Murray (*id)->data.length = sizeof(*m);
134b528cefcSMark Murray
135b528cefcSMark Murray return 0;
136b528cefcSMark Murray }
137b528cefcSMark Murray
1385e9cd1aeSAssar Westerlund
1395e9cd1aeSAssar Westerlund static krb5_error_code KRB5_CALLCONV
mcc_gen_new(krb5_context context,krb5_ccache * id)140adb0ddaeSAssar Westerlund mcc_gen_new(krb5_context context, krb5_ccache *id)
141adb0ddaeSAssar Westerlund {
142b528cefcSMark Murray krb5_mcache *m;
143adb0ddaeSAssar Westerlund
1445e9cd1aeSAssar Westerlund m = mcc_alloc(NULL);
145b528cefcSMark Murray
146b528cefcSMark Murray if (m == NULL) {
1475e9cd1aeSAssar Westerlund krb5_set_error_message(context, KRB5_CC_NOMEM,
148b528cefcSMark Murray N_("malloc: out of memory", ""));
149b528cefcSMark Murray return KRB5_CC_NOMEM;
150b528cefcSMark Murray }
151b528cefcSMark Murray
152b528cefcSMark Murray (*id)->data.data = m;
153b528cefcSMark Murray (*id)->data.length = sizeof(*m);
154b528cefcSMark Murray
155b528cefcSMark Murray return 0;
1561c43270aSJacques Vidrine }
1571c43270aSJacques Vidrine
1585e9cd1aeSAssar Westerlund static krb5_error_code KRB5_CALLCONV
mcc_initialize(krb5_context context,krb5_ccache id,krb5_principal primary_principal)159b528cefcSMark Murray mcc_initialize(krb5_context context,
1601c43270aSJacques Vidrine krb5_ccache id,
161b528cefcSMark Murray krb5_principal primary_principal)
162b528cefcSMark Murray {
163c19800e8SDoug Rabson krb5_mcache *m = MCACHE(id);
164c19800e8SDoug Rabson m->dead = 0;
165b528cefcSMark Murray m->mtime = time(NULL);
1665e9cd1aeSAssar Westerlund return krb5_copy_principal (context,
1675e9cd1aeSAssar Westerlund primary_principal,
1685e9cd1aeSAssar Westerlund &m->primary_principal);
1695e9cd1aeSAssar Westerlund }
1705e9cd1aeSAssar Westerlund
171c19800e8SDoug Rabson static int
mcc_close_internal(krb5_mcache * m)172c19800e8SDoug Rabson mcc_close_internal(krb5_mcache *m)
173c19800e8SDoug Rabson {
1745e9cd1aeSAssar Westerlund if (--m->refcnt != 0)
1755e9cd1aeSAssar Westerlund return 0;
176c19800e8SDoug Rabson
177c19800e8SDoug Rabson if (MISDEAD(m)) {
178c19800e8SDoug Rabson free (m->name);
179c19800e8SDoug Rabson return 1;
180c19800e8SDoug Rabson }
181c19800e8SDoug Rabson return 0;
1825e9cd1aeSAssar Westerlund }
1835e9cd1aeSAssar Westerlund
1845e9cd1aeSAssar Westerlund static krb5_error_code KRB5_CALLCONV
mcc_close(krb5_context context,krb5_ccache id)1855e9cd1aeSAssar Westerlund mcc_close(krb5_context context,
1865e9cd1aeSAssar Westerlund krb5_ccache id)
1875e9cd1aeSAssar Westerlund {
1885e9cd1aeSAssar Westerlund if (mcc_close_internal(MCACHE(id)))
1895e9cd1aeSAssar Westerlund krb5_data_free(&id->data);
190b528cefcSMark Murray return 0;
191b528cefcSMark Murray }
1925e9cd1aeSAssar Westerlund
1935e9cd1aeSAssar Westerlund static krb5_error_code KRB5_CALLCONV
mcc_destroy(krb5_context context,krb5_ccache id)1945e9cd1aeSAssar Westerlund mcc_destroy(krb5_context context,
1955e9cd1aeSAssar Westerlund krb5_ccache id)
1965e9cd1aeSAssar Westerlund {
1975e9cd1aeSAssar Westerlund krb5_mcache **n, *m = MCACHE(id);
198c19800e8SDoug Rabson struct link *l;
1995e9cd1aeSAssar Westerlund
2005e9cd1aeSAssar Westerlund if (m->refcnt == 0)
2015e9cd1aeSAssar Westerlund krb5_abortx(context, "mcc_destroy: refcnt already 0");
2025e9cd1aeSAssar Westerlund
2035e9cd1aeSAssar Westerlund if (!MISDEAD(m)) {
2045e9cd1aeSAssar Westerlund /* if this is an active mcache, remove it from the linked
205c19800e8SDoug Rabson list, and free all data */
2061c43270aSJacques Vidrine HEIMDAL_MUTEX_lock(&mcc_mutex);
207b528cefcSMark Murray for(n = &mcc_head; n && *n; n = &(*n)->next) {
2085e9cd1aeSAssar Westerlund if(m == *n) {
2091c43270aSJacques Vidrine *n = m->next;
2101c43270aSJacques Vidrine break;
2115e9cd1aeSAssar Westerlund }
212b528cefcSMark Murray }
213b528cefcSMark Murray HEIMDAL_MUTEX_unlock(&mcc_mutex);
214b528cefcSMark Murray if (m->primary_principal != NULL) {
215b528cefcSMark Murray krb5_free_principal (context, m->primary_principal);
216c19800e8SDoug Rabson m->primary_principal = NULL;
217b528cefcSMark Murray }
218b528cefcSMark Murray m->dead = 1;
219b528cefcSMark Murray
220b528cefcSMark Murray l = m->creds;
2215e9cd1aeSAssar Westerlund while (l != NULL) {
222b528cefcSMark Murray struct link *old;
223b528cefcSMark Murray
224b528cefcSMark Murray krb5_free_cred_contents (context, &l->cred);
225b528cefcSMark Murray old = l;
226b528cefcSMark Murray l = l->next;
227b528cefcSMark Murray free (old);
228b528cefcSMark Murray }
229b528cefcSMark Murray m->creds = NULL;
230b528cefcSMark Murray }
2315e9cd1aeSAssar Westerlund return 0;
232b528cefcSMark Murray }
233b528cefcSMark Murray
234b528cefcSMark Murray static krb5_error_code KRB5_CALLCONV
mcc_store_cred(krb5_context context,krb5_ccache id,krb5_creds * creds)2355e9cd1aeSAssar Westerlund mcc_store_cred(krb5_context context,
2365e9cd1aeSAssar Westerlund krb5_ccache id,
2375e9cd1aeSAssar Westerlund krb5_creds *creds)
238b528cefcSMark Murray {
239adb0ddaeSAssar Westerlund krb5_mcache *m = MCACHE(id);
240adb0ddaeSAssar Westerlund krb5_error_code ret;
241b528cefcSMark Murray struct link *l;
242adb0ddaeSAssar Westerlund
243b528cefcSMark Murray if (MISDEAD(m))
244b528cefcSMark Murray return ENOENT;
245b528cefcSMark Murray
246b528cefcSMark Murray l = malloc (sizeof(*l));
247b528cefcSMark Murray if (l == NULL) {
248b528cefcSMark Murray krb5_set_error_message(context, KRB5_CC_NOMEM,
249b528cefcSMark Murray N_("malloc: out of memory", ""));
250b528cefcSMark Murray return KRB5_CC_NOMEM;
251b528cefcSMark Murray }
252b528cefcSMark Murray l->next = m->creds;
253b528cefcSMark Murray m->creds = l;
254b528cefcSMark Murray memset (&l->cred, 0, sizeof(l->cred));
255b528cefcSMark Murray ret = krb5_copy_creds_contents (context, creds, &l->cred);
256b528cefcSMark Murray if (ret) {
257b528cefcSMark Murray m->creds = l->next;
258b528cefcSMark Murray free (l);
259b528cefcSMark Murray return ret;
2605e9cd1aeSAssar Westerlund }
2615e9cd1aeSAssar Westerlund m->mtime = time(NULL);
2621c43270aSJacques Vidrine return 0;
2635e9cd1aeSAssar Westerlund }
264b528cefcSMark Murray
265b528cefcSMark Murray static krb5_error_code KRB5_CALLCONV
mcc_get_principal(krb5_context context,krb5_ccache id,krb5_principal * principal)266b528cefcSMark Murray mcc_get_principal(krb5_context context,
267b528cefcSMark Murray krb5_ccache id,
268b528cefcSMark Murray krb5_principal *principal)
269b528cefcSMark Murray {
270b528cefcSMark Murray krb5_mcache *m = MCACHE(id);
271b528cefcSMark Murray
272b528cefcSMark Murray if (MISDEAD(m) || m->primary_principal == NULL)
273b528cefcSMark Murray return ENOENT;
2745e9cd1aeSAssar Westerlund return krb5_copy_principal (context,
2755e9cd1aeSAssar Westerlund m->primary_principal,
2765e9cd1aeSAssar Westerlund principal);
2775e9cd1aeSAssar Westerlund }
2785e9cd1aeSAssar Westerlund
279b528cefcSMark Murray static krb5_error_code KRB5_CALLCONV
mcc_get_first(krb5_context context,krb5_ccache id,krb5_cc_cursor * cursor)280b528cefcSMark Murray mcc_get_first (krb5_context context,
281b528cefcSMark Murray krb5_ccache id,
282b528cefcSMark Murray krb5_cc_cursor *cursor)
283b528cefcSMark Murray {
284b528cefcSMark Murray krb5_mcache *m = MCACHE(id);
285b528cefcSMark Murray
286b528cefcSMark Murray if (MISDEAD(m))
287b528cefcSMark Murray return ENOENT;
288b528cefcSMark Murray
2895e9cd1aeSAssar Westerlund *cursor = m->creds;
290b528cefcSMark Murray return 0;
291b528cefcSMark Murray }
2925e9cd1aeSAssar Westerlund
2935e9cd1aeSAssar Westerlund static krb5_error_code KRB5_CALLCONV
mcc_get_next(krb5_context context,krb5_ccache id,krb5_cc_cursor * cursor,krb5_creds * creds)2945e9cd1aeSAssar Westerlund mcc_get_next (krb5_context context,
295b528cefcSMark Murray krb5_ccache id,
296b528cefcSMark Murray krb5_cc_cursor *cursor,
297b528cefcSMark Murray krb5_creds *creds)
298b528cefcSMark Murray {
299b528cefcSMark Murray krb5_mcache *m = MCACHE(id);
300b528cefcSMark Murray struct link *l;
301b528cefcSMark Murray
302b528cefcSMark Murray if (MISDEAD(m))
303b528cefcSMark Murray return ENOENT;
304b528cefcSMark Murray
305b528cefcSMark Murray l = *cursor;
306b528cefcSMark Murray if (l != NULL) {
307b528cefcSMark Murray *cursor = l->next;
308b528cefcSMark Murray return krb5_copy_creds_contents (context,
309b528cefcSMark Murray &l->cred,
310b528cefcSMark Murray creds);
311b528cefcSMark Murray } else
312b528cefcSMark Murray return KRB5_CC_END;
313b528cefcSMark Murray }
314b528cefcSMark Murray
315b528cefcSMark Murray static krb5_error_code KRB5_CALLCONV
mcc_end_get(krb5_context context,krb5_ccache id,krb5_cc_cursor * cursor)316b528cefcSMark Murray mcc_end_get (krb5_context context,
3175e9cd1aeSAssar Westerlund krb5_ccache id,
318b528cefcSMark Murray krb5_cc_cursor *cursor)
3195e9cd1aeSAssar Westerlund {
3205e9cd1aeSAssar Westerlund return 0;
3215e9cd1aeSAssar Westerlund }
3225e9cd1aeSAssar Westerlund
3235e9cd1aeSAssar Westerlund static krb5_error_code KRB5_CALLCONV
mcc_remove_cred(krb5_context context,krb5_ccache id,krb5_flags which,krb5_creds * mcreds)324c19800e8SDoug Rabson mcc_remove_cred(krb5_context context,
3255e9cd1aeSAssar Westerlund krb5_ccache id,
3265e9cd1aeSAssar Westerlund krb5_flags which,
3275e9cd1aeSAssar Westerlund krb5_creds *mcreds)
3285e9cd1aeSAssar Westerlund {
3295e9cd1aeSAssar Westerlund krb5_mcache *m = MCACHE(id);
330b528cefcSMark Murray struct link **q, *p;
331b528cefcSMark Murray for(q = &m->creds, p = *q; p; p = *q) {
332b528cefcSMark Murray if(krb5_compare_creds(context, which, mcreds, &p->cred)) {
333b528cefcSMark Murray *q = p->next;
334b528cefcSMark Murray krb5_free_cred_contents(context, &p->cred);
335b528cefcSMark Murray free(p);
336b528cefcSMark Murray m->mtime = time(NULL);
337b528cefcSMark Murray } else
338b528cefcSMark Murray q = &p->next;
339b528cefcSMark Murray }
340c19800e8SDoug Rabson return 0;
341c19800e8SDoug Rabson }
342c19800e8SDoug Rabson
343c19800e8SDoug Rabson static krb5_error_code KRB5_CALLCONV
mcc_set_flags(krb5_context context,krb5_ccache id,krb5_flags flags)344c19800e8SDoug Rabson mcc_set_flags(krb5_context context,
345c19800e8SDoug Rabson krb5_ccache id,
346c19800e8SDoug Rabson krb5_flags flags)
347c19800e8SDoug Rabson {
348c19800e8SDoug Rabson return 0; /* XXX */
349c19800e8SDoug Rabson }
350c19800e8SDoug Rabson
351c19800e8SDoug Rabson struct mcache_iter {
352c19800e8SDoug Rabson krb5_mcache *cache;
353c19800e8SDoug Rabson };
354c19800e8SDoug Rabson
355c19800e8SDoug Rabson static krb5_error_code KRB5_CALLCONV
mcc_get_cache_first(krb5_context context,krb5_cc_cursor * cursor)356c19800e8SDoug Rabson mcc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor)
357c19800e8SDoug Rabson {
358c19800e8SDoug Rabson struct mcache_iter *iter;
359c19800e8SDoug Rabson
360c19800e8SDoug Rabson iter = calloc(1, sizeof(*iter));
361c19800e8SDoug Rabson if (iter == NULL) {
362c19800e8SDoug Rabson krb5_set_error_message(context, ENOMEM,
363c19800e8SDoug Rabson N_("malloc: out of memory", ""));
364c19800e8SDoug Rabson return ENOMEM;
365c19800e8SDoug Rabson }
366c19800e8SDoug Rabson
367c19800e8SDoug Rabson HEIMDAL_MUTEX_lock(&mcc_mutex);
368c19800e8SDoug Rabson iter->cache = mcc_head;
369c19800e8SDoug Rabson if (iter->cache)
370c19800e8SDoug Rabson iter->cache->refcnt++;
371c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&mcc_mutex);
372c19800e8SDoug Rabson
373c19800e8SDoug Rabson *cursor = iter;
374c19800e8SDoug Rabson return 0;
375c19800e8SDoug Rabson }
376c19800e8SDoug Rabson
377c19800e8SDoug Rabson static krb5_error_code KRB5_CALLCONV
mcc_get_cache_next(krb5_context context,krb5_cc_cursor cursor,krb5_ccache * id)378c19800e8SDoug Rabson mcc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id)
379c19800e8SDoug Rabson {
380c19800e8SDoug Rabson struct mcache_iter *iter = cursor;
381c19800e8SDoug Rabson krb5_error_code ret;
382c19800e8SDoug Rabson krb5_mcache *m;
383c19800e8SDoug Rabson
384c19800e8SDoug Rabson if (iter->cache == NULL)
385c19800e8SDoug Rabson return KRB5_CC_END;
386c19800e8SDoug Rabson
387c19800e8SDoug Rabson HEIMDAL_MUTEX_lock(&mcc_mutex);
388c19800e8SDoug Rabson m = iter->cache;
389c19800e8SDoug Rabson if (m->next)
390c19800e8SDoug Rabson m->next->refcnt++;
391c19800e8SDoug Rabson iter->cache = m->next;
392c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&mcc_mutex);
393c19800e8SDoug Rabson
394c19800e8SDoug Rabson ret = _krb5_cc_allocate(context, &krb5_mcc_ops, id);
395c19800e8SDoug Rabson if (ret)
396c19800e8SDoug Rabson return ret;
397c19800e8SDoug Rabson
398c19800e8SDoug Rabson (*id)->data.data = m;
399c19800e8SDoug Rabson (*id)->data.length = sizeof(*m);
400c19800e8SDoug Rabson
401c19800e8SDoug Rabson return 0;
402c19800e8SDoug Rabson }
403c19800e8SDoug Rabson
404c19800e8SDoug Rabson static krb5_error_code KRB5_CALLCONV
mcc_end_cache_get(krb5_context context,krb5_cc_cursor cursor)405c19800e8SDoug Rabson mcc_end_cache_get(krb5_context context, krb5_cc_cursor cursor)
406c19800e8SDoug Rabson {
407c19800e8SDoug Rabson struct mcache_iter *iter = cursor;
408c19800e8SDoug Rabson
409c19800e8SDoug Rabson if (iter->cache)
410c19800e8SDoug Rabson mcc_close_internal(iter->cache);
411c19800e8SDoug Rabson iter->cache = NULL;
412c19800e8SDoug Rabson free(iter);
413c19800e8SDoug Rabson return 0;
414c19800e8SDoug Rabson }
415c19800e8SDoug Rabson
416c19800e8SDoug Rabson static krb5_error_code KRB5_CALLCONV
mcc_move(krb5_context context,krb5_ccache from,krb5_ccache to)417c19800e8SDoug Rabson mcc_move(krb5_context context, krb5_ccache from, krb5_ccache to)
418c19800e8SDoug Rabson {
419c19800e8SDoug Rabson krb5_mcache *mfrom = MCACHE(from), *mto = MCACHE(to);
420c19800e8SDoug Rabson struct link *creds;
421c19800e8SDoug Rabson krb5_principal principal;
422c19800e8SDoug Rabson krb5_mcache **n;
423c19800e8SDoug Rabson
424c19800e8SDoug Rabson HEIMDAL_MUTEX_lock(&mcc_mutex);
425c19800e8SDoug Rabson
426c19800e8SDoug Rabson /* drop the from cache from the linked list to avoid lookups */
427c19800e8SDoug Rabson for(n = &mcc_head; n && *n; n = &(*n)->next) {
428c19800e8SDoug Rabson if(mfrom == *n) {
429c19800e8SDoug Rabson *n = mfrom->next;
430c19800e8SDoug Rabson break;
431c19800e8SDoug Rabson }
432c19800e8SDoug Rabson }
433c19800e8SDoug Rabson
434c19800e8SDoug Rabson /* swap creds */
435c19800e8SDoug Rabson creds = mto->creds;
436c19800e8SDoug Rabson mto->creds = mfrom->creds;
437c19800e8SDoug Rabson mfrom->creds = creds;
438c19800e8SDoug Rabson /* swap principal */
439c19800e8SDoug Rabson principal = mto->primary_principal;
440c19800e8SDoug Rabson mto->primary_principal = mfrom->primary_principal;
441c19800e8SDoug Rabson mfrom->primary_principal = principal;
442c19800e8SDoug Rabson
443c19800e8SDoug Rabson mto->mtime = mfrom->mtime = time(NULL);
444c19800e8SDoug Rabson
445c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&mcc_mutex);
446c19800e8SDoug Rabson mcc_destroy(context, from);
447c19800e8SDoug Rabson
448c19800e8SDoug Rabson return 0;
449c19800e8SDoug Rabson }
450c19800e8SDoug Rabson
451c19800e8SDoug Rabson static krb5_error_code KRB5_CALLCONV
mcc_default_name(krb5_context context,char ** str)452c19800e8SDoug Rabson mcc_default_name(krb5_context context, char **str)
453c19800e8SDoug Rabson {
454c19800e8SDoug Rabson *str = strdup("MEMORY:");
455b528cefcSMark Murray if (*str == NULL) {
456b528cefcSMark Murray krb5_set_error_message(context, ENOMEM,
457b528cefcSMark Murray N_("malloc: out of memory", ""));
458b528cefcSMark Murray return ENOMEM;
459b528cefcSMark Murray }
460b528cefcSMark Murray return 0;
461b528cefcSMark Murray }
462b528cefcSMark Murray
463b528cefcSMark Murray static krb5_error_code KRB5_CALLCONV
mcc_lastchange(krb5_context context,krb5_ccache id,krb5_timestamp * mtime)464b528cefcSMark Murray mcc_lastchange(krb5_context context, krb5_ccache id, krb5_timestamp *mtime)
465b528cefcSMark Murray {
466b528cefcSMark Murray *mtime = MCACHE(id)->mtime;
467b528cefcSMark Murray return 0;
468b528cefcSMark Murray }
469b528cefcSMark Murray
470c19800e8SDoug Rabson static krb5_error_code KRB5_CALLCONV
mcc_set_kdc_offset(krb5_context context,krb5_ccache id,krb5_deltat kdc_offset)471c19800e8SDoug Rabson mcc_set_kdc_offset(krb5_context context, krb5_ccache id, krb5_deltat kdc_offset)
472c19800e8SDoug Rabson {
473c19800e8SDoug Rabson krb5_mcache *m = MCACHE(id);
474c19800e8SDoug Rabson m->kdc_offset = kdc_offset;
475c19800e8SDoug Rabson return 0;
476c19800e8SDoug Rabson }
477b528cefcSMark Murray
478 static krb5_error_code KRB5_CALLCONV
mcc_get_kdc_offset(krb5_context context,krb5_ccache id,krb5_deltat * kdc_offset)479 mcc_get_kdc_offset(krb5_context context, krb5_ccache id, krb5_deltat *kdc_offset)
480 {
481 krb5_mcache *m = MCACHE(id);
482 *kdc_offset = m->kdc_offset;
483 return 0;
484 }
485
486
487 /**
488 * Variable containing the MEMORY based credential cache implemention.
489 *
490 * @ingroup krb5_ccache
491 */
492
493 KRB5_LIB_VARIABLE const krb5_cc_ops krb5_mcc_ops = {
494 KRB5_CC_OPS_VERSION,
495 "MEMORY",
496 mcc_get_name,
497 mcc_resolve,
498 mcc_gen_new,
499 mcc_initialize,
500 mcc_destroy,
501 mcc_close,
502 mcc_store_cred,
503 NULL, /* mcc_retrieve */
504 mcc_get_principal,
505 mcc_get_first,
506 mcc_get_next,
507 mcc_end_get,
508 mcc_remove_cred,
509 mcc_set_flags,
510 NULL,
511 mcc_get_cache_first,
512 mcc_get_cache_next,
513 mcc_end_cache_get,
514 mcc_move,
515 mcc_default_name,
516 NULL,
517 mcc_lastchange,
518 mcc_set_kdc_offset,
519 mcc_get_kdc_offset
520 };
521