1b528cefcSMark Murray /*
2*ae771770SStanislav Sedov * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan
3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray * All rights reserved.
5b528cefcSMark Murray *
6*ae771770SStanislav Sedov * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
7*ae771770SStanislav Sedov *
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
36b528cefcSMark Murray #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;
48*ae771770SStanislav Sedov time_t mtime;
49*ae771770SStanislav Sedov krb5_deltat kdc_offset;
50b528cefcSMark Murray } krb5_mcache;
51b528cefcSMark Murray
52c19800e8SDoug Rabson static HEIMDAL_MUTEX mcc_mutex = HEIMDAL_MUTEX_INITIALIZER;
535e9cd1aeSAssar Westerlund static struct krb5_mcache *mcc_head;
545e9cd1aeSAssar Westerlund
555e9cd1aeSAssar Westerlund #define MCACHE(X) ((krb5_mcache *)(X)->data.data)
565e9cd1aeSAssar Westerlund
571c43270aSJacques Vidrine #define MISDEAD(X) ((X)->dead)
585e9cd1aeSAssar Westerlund
59*ae771770SStanislav Sedov static const char* KRB5_CALLCONV
mcc_get_name(krb5_context context,krb5_ccache id)60b528cefcSMark Murray mcc_get_name(krb5_context context,
61b528cefcSMark Murray krb5_ccache id)
62b528cefcSMark Murray {
635e9cd1aeSAssar Westerlund return MCACHE(id)->name;
645e9cd1aeSAssar Westerlund }
655e9cd1aeSAssar Westerlund
66*ae771770SStanislav Sedov static krb5_mcache * KRB5_CALLCONV
mcc_alloc(const char * name)675e9cd1aeSAssar Westerlund mcc_alloc(const char *name)
685e9cd1aeSAssar Westerlund {
69c19800e8SDoug Rabson krb5_mcache *m, *m_c;
70*ae771770SStanislav Sedov int ret = 0;
71adb0ddaeSAssar Westerlund
725e9cd1aeSAssar Westerlund ALLOC(m, 1);
735e9cd1aeSAssar Westerlund if(m == NULL)
745e9cd1aeSAssar Westerlund return NULL;
755e9cd1aeSAssar Westerlund if(name == NULL)
76*ae771770SStanislav Sedov ret = asprintf(&m->name, "%p", m);
775e9cd1aeSAssar Westerlund else
785e9cd1aeSAssar Westerlund m->name = strdup(name);
79*ae771770SStanislav Sedov if(ret < 0 || m->name == NULL) {
805e9cd1aeSAssar Westerlund free(m);
815e9cd1aeSAssar Westerlund return NULL;
825e9cd1aeSAssar Westerlund }
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);
92c19800e8SDoug Rabson return NULL;
93c19800e8SDoug Rabson }
94c19800e8SDoug Rabson
951c43270aSJacques Vidrine m->dead = 0;
965e9cd1aeSAssar Westerlund m->refcnt = 1;
975e9cd1aeSAssar Westerlund m->primary_principal = NULL;
985e9cd1aeSAssar Westerlund m->creds = NULL;
99*ae771770SStanislav Sedov m->mtime = time(NULL);
100*ae771770SStanislav Sedov m->kdc_offset = 0;
1015e9cd1aeSAssar Westerlund m->next = mcc_head;
1025e9cd1aeSAssar Westerlund mcc_head = m;
103c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&mcc_mutex);
1045e9cd1aeSAssar Westerlund return m;
105b528cefcSMark Murray }
106b528cefcSMark Murray
107*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
mcc_resolve(krb5_context context,krb5_ccache * id,const char * res)108b528cefcSMark Murray mcc_resolve(krb5_context context, krb5_ccache *id, const char *res)
109b528cefcSMark Murray {
1105e9cd1aeSAssar Westerlund krb5_mcache *m;
1115e9cd1aeSAssar Westerlund
112c19800e8SDoug Rabson 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;
116c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&mcc_mutex);
1175e9cd1aeSAssar Westerlund
1185e9cd1aeSAssar Westerlund if (m != NULL) {
1195e9cd1aeSAssar Westerlund m->refcnt++;
1205e9cd1aeSAssar Westerlund (*id)->data.data = m;
1215e9cd1aeSAssar Westerlund (*id)->data.length = sizeof(*m);
1225e9cd1aeSAssar Westerlund return 0;
123b528cefcSMark Murray }
124b528cefcSMark Murray
1255e9cd1aeSAssar Westerlund m = mcc_alloc(res);
126adb0ddaeSAssar Westerlund if (m == NULL) {
127*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_CC_NOMEM,
128*ae771770SStanislav Sedov N_("malloc: out of memory", ""));
1295e9cd1aeSAssar Westerlund return KRB5_CC_NOMEM;
130adb0ddaeSAssar Westerlund }
1315e9cd1aeSAssar Westerlund
1325e9cd1aeSAssar Westerlund (*id)->data.data = m;
1335e9cd1aeSAssar Westerlund (*id)->data.length = sizeof(*m);
1345e9cd1aeSAssar Westerlund
1355e9cd1aeSAssar Westerlund return 0;
1365e9cd1aeSAssar Westerlund }
1375e9cd1aeSAssar Westerlund
1385e9cd1aeSAssar Westerlund
139*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
mcc_gen_new(krb5_context context,krb5_ccache * id)140b528cefcSMark Murray mcc_gen_new(krb5_context context, krb5_ccache *id)
141b528cefcSMark Murray {
142b528cefcSMark Murray krb5_mcache *m;
143b528cefcSMark Murray
1445e9cd1aeSAssar Westerlund m = mcc_alloc(NULL);
1455e9cd1aeSAssar Westerlund
146adb0ddaeSAssar Westerlund if (m == NULL) {
147*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_CC_NOMEM,
148*ae771770SStanislav Sedov N_("malloc: out of memory", ""));
149b528cefcSMark Murray return KRB5_CC_NOMEM;
150adb0ddaeSAssar Westerlund }
1515e9cd1aeSAssar Westerlund
152b528cefcSMark Murray (*id)->data.data = m;
153b528cefcSMark Murray (*id)->data.length = sizeof(*m);
1545e9cd1aeSAssar Westerlund
155b528cefcSMark Murray return 0;
156b528cefcSMark Murray }
157b528cefcSMark Murray
158*ae771770SStanislav Sedov 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,
160b528cefcSMark Murray krb5_ccache id,
161b528cefcSMark Murray krb5_principal primary_principal)
162b528cefcSMark Murray {
1631c43270aSJacques Vidrine krb5_mcache *m = MCACHE(id);
1641c43270aSJacques Vidrine m->dead = 0;
165*ae771770SStanislav Sedov m->mtime = time(NULL);
1665e9cd1aeSAssar Westerlund return krb5_copy_principal (context,
167b528cefcSMark Murray primary_principal,
1681c43270aSJacques Vidrine &m->primary_principal);
169b528cefcSMark Murray }
170b528cefcSMark Murray
171c19800e8SDoug Rabson static int
mcc_close_internal(krb5_mcache * m)172c19800e8SDoug Rabson mcc_close_internal(krb5_mcache *m)
173b528cefcSMark Murray {
1745e9cd1aeSAssar Westerlund if (--m->refcnt != 0)
1755e9cd1aeSAssar Westerlund return 0;
1765e9cd1aeSAssar Westerlund
1775e9cd1aeSAssar Westerlund if (MISDEAD(m)) {
1785e9cd1aeSAssar Westerlund free (m->name);
179c19800e8SDoug Rabson return 1;
180c19800e8SDoug Rabson }
181c19800e8SDoug Rabson return 0;
1825e9cd1aeSAssar Westerlund }
1835e9cd1aeSAssar Westerlund
184*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
mcc_close(krb5_context context,krb5_ccache id)185c19800e8SDoug Rabson mcc_close(krb5_context context,
186c19800e8SDoug Rabson krb5_ccache id)
187c19800e8SDoug Rabson {
188c19800e8SDoug Rabson if (mcc_close_internal(MCACHE(id)))
189c19800e8SDoug Rabson krb5_data_free(&id->data);
1905e9cd1aeSAssar Westerlund return 0;
1915e9cd1aeSAssar Westerlund }
1925e9cd1aeSAssar Westerlund
193*ae771770SStanislav Sedov 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);
198b528cefcSMark Murray struct link *l;
199b528cefcSMark Murray
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
2055e9cd1aeSAssar Westerlund list, and free all data */
206c19800e8SDoug Rabson HEIMDAL_MUTEX_lock(&mcc_mutex);
2075e9cd1aeSAssar Westerlund for(n = &mcc_head; n && *n; n = &(*n)->next) {
2085e9cd1aeSAssar Westerlund if(m == *n) {
2095e9cd1aeSAssar Westerlund *n = m->next;
2105e9cd1aeSAssar Westerlund break;
2115e9cd1aeSAssar Westerlund }
2125e9cd1aeSAssar Westerlund }
213c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&mcc_mutex);
2141c43270aSJacques Vidrine if (m->primary_principal != NULL) {
215b528cefcSMark Murray krb5_free_principal (context, m->primary_principal);
2165e9cd1aeSAssar Westerlund m->primary_principal = NULL;
2171c43270aSJacques Vidrine }
2181c43270aSJacques Vidrine m->dead = 1;
2195e9cd1aeSAssar Westerlund
220b528cefcSMark Murray l = m->creds;
221b528cefcSMark Murray while (l != NULL) {
222b528cefcSMark Murray struct link *old;
223b528cefcSMark Murray
224c19800e8SDoug Rabson krb5_free_cred_contents (context, &l->cred);
225b528cefcSMark Murray old = l;
226b528cefcSMark Murray l = l->next;
227b528cefcSMark Murray free (old);
228b528cefcSMark Murray }
2295e9cd1aeSAssar Westerlund m->creds = NULL;
230b528cefcSMark Murray }
231b528cefcSMark Murray return 0;
232b528cefcSMark Murray }
233b528cefcSMark Murray
234*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
mcc_store_cred(krb5_context context,krb5_ccache id,krb5_creds * creds)235b528cefcSMark Murray mcc_store_cred(krb5_context context,
236b528cefcSMark Murray krb5_ccache id,
237b528cefcSMark Murray krb5_creds *creds)
238b528cefcSMark Murray {
2395e9cd1aeSAssar Westerlund krb5_mcache *m = MCACHE(id);
240b528cefcSMark Murray krb5_error_code ret;
241b528cefcSMark Murray struct link *l;
242b528cefcSMark Murray
2435e9cd1aeSAssar Westerlund if (MISDEAD(m))
2445e9cd1aeSAssar Westerlund return ENOENT;
2455e9cd1aeSAssar Westerlund
246b528cefcSMark Murray l = malloc (sizeof(*l));
247adb0ddaeSAssar Westerlund if (l == NULL) {
248*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_CC_NOMEM,
249*ae771770SStanislav Sedov N_("malloc: out of memory", ""));
250b528cefcSMark Murray return KRB5_CC_NOMEM;
251adb0ddaeSAssar Westerlund }
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;
260b528cefcSMark Murray }
261*ae771770SStanislav Sedov m->mtime = time(NULL);
262b528cefcSMark Murray return 0;
263b528cefcSMark Murray }
264b528cefcSMark Murray
265*ae771770SStanislav Sedov 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 {
2705e9cd1aeSAssar Westerlund krb5_mcache *m = MCACHE(id);
2715e9cd1aeSAssar Westerlund
2721c43270aSJacques Vidrine if (MISDEAD(m) || m->primary_principal == NULL)
2735e9cd1aeSAssar Westerlund return ENOENT;
274b528cefcSMark Murray return krb5_copy_principal (context,
275b528cefcSMark Murray m->primary_principal,
276b528cefcSMark Murray principal);
277b528cefcSMark Murray }
278b528cefcSMark Murray
279*ae771770SStanislav Sedov 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 {
2845e9cd1aeSAssar Westerlund krb5_mcache *m = MCACHE(id);
2855e9cd1aeSAssar Westerlund
2865e9cd1aeSAssar Westerlund if (MISDEAD(m))
2875e9cd1aeSAssar Westerlund return ENOENT;
2885e9cd1aeSAssar Westerlund
289b528cefcSMark Murray *cursor = m->creds;
290b528cefcSMark Murray return 0;
291b528cefcSMark Murray }
292b528cefcSMark Murray
293*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
mcc_get_next(krb5_context context,krb5_ccache id,krb5_cc_cursor * cursor,krb5_creds * creds)294b528cefcSMark Murray mcc_get_next (krb5_context context,
295b528cefcSMark Murray krb5_ccache id,
296b528cefcSMark Murray krb5_cc_cursor *cursor,
297b528cefcSMark Murray krb5_creds *creds)
298b528cefcSMark Murray {
2995e9cd1aeSAssar Westerlund krb5_mcache *m = MCACHE(id);
300b528cefcSMark Murray struct link *l;
301b528cefcSMark Murray
3025e9cd1aeSAssar Westerlund if (MISDEAD(m))
3035e9cd1aeSAssar Westerlund return ENOENT;
3045e9cd1aeSAssar Westerlund
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
315*ae771770SStanislav Sedov 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,
317b528cefcSMark Murray krb5_ccache id,
318b528cefcSMark Murray krb5_cc_cursor *cursor)
319b528cefcSMark Murray {
320b528cefcSMark Murray return 0;
321b528cefcSMark Murray }
322b528cefcSMark Murray
323*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
mcc_remove_cred(krb5_context context,krb5_ccache id,krb5_flags which,krb5_creds * mcreds)324b528cefcSMark Murray mcc_remove_cred(krb5_context context,
325b528cefcSMark Murray krb5_ccache id,
326b528cefcSMark Murray krb5_flags which,
3275e9cd1aeSAssar Westerlund krb5_creds *mcreds)
328b528cefcSMark Murray {
3295e9cd1aeSAssar Westerlund krb5_mcache *m = MCACHE(id);
3305e9cd1aeSAssar Westerlund struct link **q, *p;
3315e9cd1aeSAssar Westerlund for(q = &m->creds, p = *q; p; p = *q) {
3325e9cd1aeSAssar Westerlund if(krb5_compare_creds(context, which, mcreds, &p->cred)) {
3335e9cd1aeSAssar Westerlund *q = p->next;
334c19800e8SDoug Rabson krb5_free_cred_contents(context, &p->cred);
3355e9cd1aeSAssar Westerlund free(p);
336*ae771770SStanislav Sedov m->mtime = time(NULL);
3375e9cd1aeSAssar Westerlund } else
3385e9cd1aeSAssar Westerlund q = &p->next;
3395e9cd1aeSAssar Westerlund }
3405e9cd1aeSAssar Westerlund return 0;
341b528cefcSMark Murray }
342b528cefcSMark Murray
343*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
mcc_set_flags(krb5_context context,krb5_ccache id,krb5_flags flags)344b528cefcSMark Murray mcc_set_flags(krb5_context context,
345b528cefcSMark Murray krb5_ccache id,
346b528cefcSMark Murray krb5_flags flags)
347b528cefcSMark Murray {
348b528cefcSMark Murray return 0; /* XXX */
349b528cefcSMark Murray }
350b528cefcSMark Murray
351c19800e8SDoug Rabson struct mcache_iter {
352c19800e8SDoug Rabson krb5_mcache *cache;
353c19800e8SDoug Rabson };
354c19800e8SDoug Rabson
355*ae771770SStanislav Sedov 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) {
362*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM,
363*ae771770SStanislav Sedov 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
377*ae771770SStanislav Sedov 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
404*ae771770SStanislav Sedov 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
416*ae771770SStanislav Sedov 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
443*ae771770SStanislav Sedov mto->mtime = mfrom->mtime = time(NULL);
444*ae771770SStanislav Sedov
445c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&mcc_mutex);
446c19800e8SDoug Rabson mcc_destroy(context, from);
447c19800e8SDoug Rabson
448c19800e8SDoug Rabson return 0;
449c19800e8SDoug Rabson }
450c19800e8SDoug Rabson
451*ae771770SStanislav Sedov 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:");
455c19800e8SDoug Rabson if (*str == NULL) {
456*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM,
457*ae771770SStanislav Sedov N_("malloc: out of memory", ""));
458c19800e8SDoug Rabson return ENOMEM;
459c19800e8SDoug Rabson }
460c19800e8SDoug Rabson return 0;
461c19800e8SDoug Rabson }
462c19800e8SDoug Rabson
463*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
mcc_lastchange(krb5_context context,krb5_ccache id,krb5_timestamp * mtime)464*ae771770SStanislav Sedov mcc_lastchange(krb5_context context, krb5_ccache id, krb5_timestamp *mtime)
465*ae771770SStanislav Sedov {
466*ae771770SStanislav Sedov *mtime = MCACHE(id)->mtime;
467*ae771770SStanislav Sedov return 0;
468*ae771770SStanislav Sedov }
469*ae771770SStanislav Sedov
470*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
mcc_set_kdc_offset(krb5_context context,krb5_ccache id,krb5_deltat kdc_offset)471*ae771770SStanislav Sedov mcc_set_kdc_offset(krb5_context context, krb5_ccache id, krb5_deltat kdc_offset)
472*ae771770SStanislav Sedov {
473*ae771770SStanislav Sedov krb5_mcache *m = MCACHE(id);
474*ae771770SStanislav Sedov m->kdc_offset = kdc_offset;
475*ae771770SStanislav Sedov return 0;
476*ae771770SStanislav Sedov }
477*ae771770SStanislav Sedov
478*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
mcc_get_kdc_offset(krb5_context context,krb5_ccache id,krb5_deltat * kdc_offset)479*ae771770SStanislav Sedov mcc_get_kdc_offset(krb5_context context, krb5_ccache id, krb5_deltat *kdc_offset)
480*ae771770SStanislav Sedov {
481*ae771770SStanislav Sedov krb5_mcache *m = MCACHE(id);
482*ae771770SStanislav Sedov *kdc_offset = m->kdc_offset;
483*ae771770SStanislav Sedov return 0;
484*ae771770SStanislav Sedov }
485*ae771770SStanislav Sedov
486c19800e8SDoug Rabson
487c19800e8SDoug Rabson /**
488c19800e8SDoug Rabson * Variable containing the MEMORY based credential cache implemention.
489c19800e8SDoug Rabson *
490c19800e8SDoug Rabson * @ingroup krb5_ccache
491c19800e8SDoug Rabson */
492c19800e8SDoug Rabson
493*ae771770SStanislav Sedov KRB5_LIB_VARIABLE const krb5_cc_ops krb5_mcc_ops = {
494*ae771770SStanislav Sedov KRB5_CC_OPS_VERSION,
495b528cefcSMark Murray "MEMORY",
496b528cefcSMark Murray mcc_get_name,
497b528cefcSMark Murray mcc_resolve,
498b528cefcSMark Murray mcc_gen_new,
499b528cefcSMark Murray mcc_initialize,
500b528cefcSMark Murray mcc_destroy,
501b528cefcSMark Murray mcc_close,
502b528cefcSMark Murray mcc_store_cred,
503b528cefcSMark Murray NULL, /* mcc_retrieve */
504b528cefcSMark Murray mcc_get_principal,
505b528cefcSMark Murray mcc_get_first,
506b528cefcSMark Murray mcc_get_next,
507b528cefcSMark Murray mcc_end_get,
508b528cefcSMark Murray mcc_remove_cred,
509c19800e8SDoug Rabson mcc_set_flags,
510c19800e8SDoug Rabson NULL,
511c19800e8SDoug Rabson mcc_get_cache_first,
512c19800e8SDoug Rabson mcc_get_cache_next,
513c19800e8SDoug Rabson mcc_end_cache_get,
514c19800e8SDoug Rabson mcc_move,
515*ae771770SStanislav Sedov mcc_default_name,
516*ae771770SStanislav Sedov NULL,
517*ae771770SStanislav Sedov mcc_lastchange,
518*ae771770SStanislav Sedov mcc_set_kdc_offset,
519*ae771770SStanislav Sedov mcc_get_kdc_offset
520b528cefcSMark Murray };
521